From b3ac46dee93d2c67dfa7c629f0b28c28fa70a488 Mon Sep 17 00:00:00 2001 From: Michael Bos Date: Wed, 11 Mar 2020 21:05:24 +0100 Subject: [PATCH 1/4] Changed the icon colors to represent the new logo --- src/qt/res/icons/add.png | Bin 16241 -> 9089 bytes src/qt/res/icons/browse.png | Bin 19027 -> 11263 bytes src/qt/res/icons/clock1.png | Bin 18737 -> 11548 bytes src/qt/res/icons/clock2.png | Bin 18384 -> 10868 bytes src/qt/res/icons/clock3.png | Bin 17971 -> 10171 bytes src/qt/res/icons/clock4.png | Bin 17774 -> 9770 bytes src/qt/res/icons/clock5.png | Bin 17523 -> 9686 bytes src/qt/res/icons/configure.png | Bin 19049 -> 12056 bytes src/qt/res/icons/debugwindow.png | Bin 16882 -> 9692 bytes src/qt/res/icons/edit.png | Bin 17612 -> 10436 bytes src/qt/res/icons/editconf.png | Bin 16471 -> 7709 bytes src/qt/res/icons/editcopy.png | Bin 16340 -> 8417 bytes src/qt/res/icons/editpaste.png | Bin 16762 -> 10319 bytes src/qt/res/icons/export.png | Bin 17625 -> 11517 bytes src/qt/res/icons/eye.png | Bin 18230 -> 10285 bytes src/qt/res/icons/eye_minus.png | Bin 18539 -> 11101 bytes src/qt/res/icons/eye_plus.png | Bin 18770 -> 11298 bytes src/qt/res/icons/filesave.png | Bin 18197 -> 11120 bytes src/qt/res/icons/folder.png | Bin 15664 -> 6596 bytes src/qt/res/icons/key.png | Bin 17398 -> 9793 bytes src/qt/res/icons/notsynced.png | Bin 17065 -> 13268 bytes src/qt/res/icons/quit.png | Bin 17065 -> 13266 bytes src/qt/res/icons/staking_on.png | Bin 17242 -> 9668 bytes src/qt/res/icons/synced.png | Bin 17317 -> 11336 bytes src/qt/res/icons/transaction0.png | Bin 17143 -> 8909 bytes src/qt/res/icons/transaction2.png | Bin 17317 -> 11336 bytes src/qt/res/icons/transaction_conflicted.png | Bin 17065 -> 13265 bytes src/qt/res/icons/tx_inout.png | Bin 17473 -> 10058 bytes src/qt/res/icons/tx_input.png | Bin 17523 -> 9647 bytes src/qt/res/icons/tx_mined.png | Bin 16956 -> 9227 bytes src/qt/res/icons/tx_output.png | Bin 17564 -> 9785 bytes src/secp256k1/.gitignore | 2 + src/secp256k1/.travis.yml | 9 +- src/secp256k1/Makefile.am | 34 +- src/secp256k1/README.md | 8 +- .../build-aux/m4/ax_jni_include_dir.m4 | 47 +- src/secp256k1/build-aux/m4/bitcoin_secp.m4 | 1 - src/secp256k1/configure.ac | 52 +- src/secp256k1/contrib/lax_der_parsing.h | 10 +- .../contrib/lax_der_privatekey_parsing.h | 10 +- src/secp256k1/include/secp256k1.h | 97 ++- src/secp256k1/include/secp256k1_ecdh.h | 16 +- src/secp256k1/include/secp256k1_recovery.h | 16 +- src/secp256k1/sage/group_prover.sage | 4 +- src/secp256k1/src/asm/field_10x26_arm.s | 4 +- src/secp256k1/src/basic-config.h | 9 +- src/secp256k1/src/bench.h | 24 +- src/secp256k1/src/bench_ecdh.c | 8 +- src/secp256k1/src/bench_ecmult.c | 196 +++++ src/secp256k1/src/bench_internal.c | 77 +- src/secp256k1/src/bench_recover.c | 8 +- src/secp256k1/src/bench_sign.c | 12 +- src/secp256k1/src/ecdsa.h | 6 +- src/secp256k1/src/ecdsa_impl.h | 36 +- src/secp256k1/src/eckey.h | 6 +- src/secp256k1/src/eckey_impl.h | 17 +- src/secp256k1/src/ecmult.h | 24 +- src/secp256k1/src/ecmult_const.h | 6 +- src/secp256k1/src/ecmult_const_impl.h | 22 +- src/secp256k1/src/ecmult_gen.h | 6 +- src/secp256k1/src/ecmult_gen_impl.h | 8 +- src/secp256k1/src/ecmult_impl.h | 748 ++++++++++++++++-- src/secp256k1/src/field.h | 11 +- src/secp256k1/src/field_10x26.h | 7 +- src/secp256k1/src/field_10x26_impl.h | 75 +- src/secp256k1/src/field_5x52.h | 6 +- src/secp256k1/src/field_5x52_asm_impl.h | 6 +- src/secp256k1/src/field_5x52_impl.h | 97 ++- src/secp256k1/src/field_5x52_int128_impl.h | 6 +- src/secp256k1/src/field_impl.h | 6 +- src/secp256k1/src/gen_context.c | 2 +- src/secp256k1/src/group.h | 9 +- src/secp256k1/src/group_impl.h | 74 +- src/secp256k1/src/hash.h | 32 +- src/secp256k1/src/hash_impl.h | 55 +- .../src/java/org/bitcoin/NativeSecp256k1.java | 34 +- .../java/org/bitcoin/NativeSecp256k1Test.java | 21 - .../src/java/org_bitcoin_NativeSecp256k1.c | 34 - .../src/java/org_bitcoin_NativeSecp256k1.h | 8 - src/secp256k1/src/modules/ecdh/main_impl.h | 10 +- src/secp256k1/src/modules/ecdh/tests_impl.h | 38 +- .../src/modules/recovery/main_impl.h | 8 +- .../src/modules/recovery/tests_impl.h | 149 +++- src/secp256k1/src/num.h | 6 +- src/secp256k1/src/num_gmp.h | 6 +- src/secp256k1/src/num_gmp_impl.h | 6 +- src/secp256k1/src/num_impl.h | 6 +- src/secp256k1/src/scalar.h | 10 +- src/secp256k1/src/scalar_4x64.h | 6 +- src/secp256k1/src/scalar_4x64_impl.h | 6 +- src/secp256k1/src/scalar_8x32.h | 6 +- src/secp256k1/src/scalar_8x32_impl.h | 6 +- src/secp256k1/src/scalar_impl.h | 216 +++-- src/secp256k1/src/scalar_low.h | 15 + src/secp256k1/src/scalar_low_impl.h | 114 +++ src/secp256k1/src/scratch.h | 35 + src/secp256k1/src/scratch_impl.h | 77 ++ src/secp256k1/src/secp256k1.c | 68 +- src/secp256k1/src/testrand.h | 6 +- src/secp256k1/src/testrand_impl.h | 8 +- src/secp256k1/src/tests.c | 551 ++++++++++++- src/secp256k1/src/tests_exhaustive.c | 511 ++++++++++++ src/secp256k1/src/util.h | 19 +- 103 files changed, 3165 insertions(+), 724 deletions(-) create mode 100644 src/secp256k1/src/bench_ecmult.c create mode 100644 src/secp256k1/src/scalar_low.h create mode 100644 src/secp256k1/src/scalar_low_impl.h create mode 100644 src/secp256k1/src/scratch.h create mode 100644 src/secp256k1/src/scratch_impl.h create mode 100644 src/secp256k1/src/tests_exhaustive.c diff --git a/src/qt/res/icons/add.png b/src/qt/res/icons/add.png index 2eaa75da6c0ba9f340bbb6d60530e2c22baec990..a4fc48d8ac98b9891fcddb1cb4f48fa8f832d977 100644 GIT binary patch literal 9089 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 BQAYp( literal 19027 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 diff --git a/src/qt/res/icons/clock1.png b/src/qt/res/icons/clock1.png index 6f852c09d9e40b93427de4d66d63a7e4e70b8289..921ba79797695f731007bf47721a8f305f4a299e 100644 GIT binary patch literal 11548 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 literal 18737 zcmeI3XH-*J*T+L>QY|0?0)`k=z>r2uC<;N^h)Nw$Q9}|Sm<9=ufGA}U3pFS@s3ldzFc3o zr35mIVM3y?0;ncD1{>%Nfmko%u}S3hR4y!l8bo8-!22sN!eKOu4g7aAH?$j@NDZbr zM}<*6qn3G*qt=u06!;=rMQa`b2*99nNiZIR&g2kyHt_Md1mL%*83l)pcj2zLf!m1& zg!#IyfDu_?RG68GIg*UQS;8#vCKxlkCDwEy42#B?qtJL1#uSOh5YTu68Uy?Mg4-$r zzpTS3fdmf+$Irt7mJK|Z%ViT#sL04jlSrHiD=Y|w!Q=5LG!})$B7q)A4xh;-@sLc; z+=(Dx;y6$_80@bDF*%>v0TfX@5*vjvL8E>q zqL9C8*x_OH@u^YBC@P)Gpfb4}K!^FMjvdV6vN*x4Ukv%x{mX%YoVdAt9s8&AWiWm^ zG>5w+0zmK?=}(m$FFu=!@}P29;bCOzk_g~Z=Kk#JxwOD<$@wml$n(p&Q+c#s$V8qA z+4xeJ$dEN~tps8imBeL*d9he@+lf`S;tN6;ktkYK7O(}s)0h-iB*)Mi1(tlv_qS+N z2NIWRD^db05s5MN!r%!w9KjTgL|YQj=t)5)dV*rOu_&}a{+AedQ4Fk^7a+x&5iq#P zF(&l{#{l*Zg~TQOqbQU6PKrYz69QRb3=-Ft#vlbzQEXNk-yGrX-{#9tY4f z!{P#{Xi|WwspU9CH@C_1A3{5@$l;>h@;NjG2#q0GV$c{ekQF?RinOpaHACXD*gzx+ zL$S0#V@xS#80?qOljJ{yULHmRDjkVFsgG#(|8|I2#nuTMn%UIq?t zjS^LVI_-ZU5gby)|11qSGA;mZ5om$LkOFW>b4yb!GQa{GfDE8mTAEtma2T?=>6bMB zt29_5(Rfi^!{P{NECBdTdVY52dCxqnsx zC&2ux%>C*#`G1hPiJka;P5e^If2^U_q8kYUP=A41KpL-m7;DrIZQs_+M1NmV9i@kl z_qV{JffouR`ur@N>;_By#7if;!P0L^Zzhdv3mj1669qL-Qi<+%CXQlH;KrP4Yi?$S zGqXm4o56||G#-`i>p%m}OpfRzz+eF;<07!AmU94F7bRoUI{J`5b>r2mv}xPuLKteh$-jv`H&j;j{-~s^=Z%S~9=L7OeaDjk`Hzl~l^8tA!xIjR}n__V(etY1S z$^@RWjRYR2{ovGk4R{n6Mt1gagFvDTAduJu2xRyZ@cj}32}eU9UF#qa!fps;7E7@9 ziX-s&?{pUjJ1<^y&ptlayJ6g`3}3Z zgO3C>DBdTmTjjMdtMrV|iLxS-Raf#04rW2M|5iPE;vlS8#>;DlRtLmoq~`H*Pi6k- z!_mIz_qKKA_x)M2b^8V*>+#Y3r|TaZB-KX6!51rbPW6H&yo;Rnw_2y_2KP;sQs-k; z7UPPweDf~Oj3zeCC94mY)UA7@0d~~-1T-hq!jwe{jdEpIkGFQuRmeK(5gf8idQW? znrLJ*50WCBE0h+#3Ds@xa1N7QA-z|=XMZe>T%~u?@Ikoi#zOV1iggz2jEa?q+@Vt* zYm7=;NU@-i`S4B`pPobZeo{*@Mh>Blkq3Ot-i>y=D$x);RczZ8l7Ej7QsW|AmcP8} zAd%OvyY=aewhd-(CfgqDn7%W)rn|=44w-n+r)sklE-rU^>kGAgEv+l^YNEm;C^|5k zdzd>!U4uvWww@{<6fP)MV#~8l*jleVN-`cU*(ord+j+KMdXu!qvCWlUJNIYB4mACy zFy~-uRt8=#Bn_egT_jf|U8W&@T{^B+dhPYw?`-9ApgHb&)dl#{<>ev$n~41w|3xiLJE|5$#1YA3xqCfirAT&_>{260W^%wzH&A=Xn0Z*{2ORUBKDrbXyU^*++2 z*?@^}cRt^DWrVraqv}qGhK;tMEu2u>uaf-t`sbN#sjuR)9c!SYUB#7{>UTF{lj2$q zb#dL($7EwVo2RWEjuxu8_JzAo4bm@$Rw#DLFO_+$Knh(d^YNJLxV`gn6@W~>U~hO)=Auoz)?vh2r$p7sk}9_#W{HTBvanpgK*Ik*+3%?MGmC^%Ji zvaa=nR1wA=nfNhuE`O1kQa*I=Xk@upJ=+d3h`LyjUX`bck%qo~ zOmls;U46a=B&lHIljZ{XV}Dv6_#3fHYI&zlSH7?A)YWcKjYphy(aXI@qf$D~en@Zo zW57P63is*-g!q;t%oX14@#XonMyGc0<&ADXdgB&$oM7N+nPcJEdoyxi!NU@x!}IpR zv)}e-DlL9nDO9-DwMXefGEe31FoI8DXLsNm3;6f4=f`D1PRBklYD)Gywf*CV-HMfn zdWUjY2I{U(y_JhDimyM6Xj81&bxyqkQ~y_?Hz{KCb}ywmi)ODm$HT`u=R@)w-3As{ zANjp~@v8^ThX%HKv}u!D)*G%aZ1ESCm!OJwK;Bn`JTyV%#U<%fVHiRKhfZF@t)Y4!M@Q?X_fh|Yu;D;TLp4?Pqj#K4V|__XZbDxmv>abL=Q;L+pNrnMABU181)M6p)qLIR$tlDE(*|4Q z?rjwdZT_08wl=V#jHT>4urcJaU-2}ByRWb5UYI)8*fiLle{STGopTO-@99;;^i_FI zeZ{h`)mLur^=K&D=iHa~rl4VU)NRfT1r5kWT-o^p`9&8lDqYVk?nMMUm>=gm$gi*U zomJM6)W7AaVs$9%l36t!#hf0X(#|M7a1`iVp7>Oou5_;;ww0$k5MP zoYz+uEiupHJEXY@>ysHZ)Vae`=zEUtNjE^HjgjQa_GuIIySk=!CsPU>WAZlo>kSjt z28(k!|CARnPO&1zlagS;6_rWu~t6?RqP_GG;H7*3fG1jiaCW zpmTk`HtX#wRCj#49l27C0OyxJsSa#gzNSw0%H=ILakFh3Go$BLzC2AT`@KRj^?gP! z?g2a4+y8?}uggcHvMXEgYp#~WCO-8*_+QDZPQ|X-P_&D+aNRS~y)qm8Y#*tc=Qoh! zc4d@m1PVNxs#b4$cPd3?WyZsn2kgb7#AUvY3A(IMAN}B}qLMNrLT+%W{_!!SZ_hJr zB|g9MT(!^h25dk%v;aT z%uGLw@7Q8qaKOOhaL|pWOpEp>+cMK{wHvtT^H0B6IPK~*SWQyL+w|~?Wu!L|F`dJT z$vAjb#OYkO@*Nq%qMQQZmQ$4UBMIhth5ojrct+~&(>>}>&bYa9N(5solXITknsSoi zk?rZIf}|l(QXi*h2Jue`ZTN@I%-?0eHW^dpFR00sHBPrTcE98?!1lZmT-cwvSny)* zn!+?C?k8`d;q-2KjWzd=6b~;lcA2LKRdoz8FquE164jltbgWT22_}2ykiE8HwLsqERS#)z%@m<=*Yi)cgkdn zT)>;(s~)ZSlev7r2Qg=f`QefmmjfCTDoX3W#jly!RA!1~9y`AAEKYDKCvW`>Rqw0T_PMh?8gIvsmVZb}bHHlu2%Zy~abGAFP5gt=&<43ha@>?VHwc32>)Yv=Dx@|M+ zU6y4y=9jE|+H61HdzIB(KE|V^F+L-o5&cxvGmezCTZh!6N-E93Z)QVkN!Z2RZvcmIGwvs?<4YZHVYbuEC zkE+{?UUJLb_$a9`!_C-?p~ZBbXF zb<)0e<-_XfGgG4KvKBbYJzzy=5JydfhlZ%vd!InPOAE8Pv)TIX83-eRlwRoAz@7Zi zQT)go&a3lAb7o!X!8Fc30<~>(cz6e~114+TuN+z*fX(cS*qb1w=X8fCKncnrYin%w z#GFuVeP*@bQYHMQCMw*TrO(!ox=a4!rS}~8rNJVt-Wqr!*0E=u%$y_rF;yM>ldy*O z(7Yp4thnZI{d2~;_1$UeCV!rjR&G5qlEX>Y-e%%^LT1yn=Tc$%Z4J)Ap`}y*TfqP( zt=&IO?WJw#*lqirAuCH3GItaRhM{QF1J+LIhtAD8 zt7Fu9pC9Bde4&~5ralp2p;&6n#tV{;m@n>^HIy~|t3jh~*7ZN}Bf;@Ox!nck?_AAh zoiq63p`K6%vHpX^~b#pb@z4`K%@QB(1|w&S9rX4f~q^o7qd?1%KA;svDXt+ zJx_RA`^rYaunMDQX`R%lci?i+=+IM@kd1{79#r~$vYKGzY@XhucgGeFe)O3Ub1pfN zu=5$xn{&arZe50I%L{!ajhWNy_7J6;kGbb64CRKjo*1qQ)nC2sMAwie^kHWIEECAe zbniU7F4*h+`ce#m;Ck)Z0pMKSY^Ae`OBmqZ#67o z(N5|<==0mtKA8UUkGHAor|%!y8d9$3abRkx>;pIKEFRQvUds7)%}7CuQe>(gj9Hy= zEx*yZ_nkXsZgcX&(OXXOI?pqO*vmA*)_I5!jM`b>c!xb+`DJU4&--m^c+`$FoDFY1 vf?TfRPuZopU7PVl5OJ|!yWOo%t&lBqj~S-y>~RMENI_hdEORKbUl;!$5i;`B diff --git a/src/qt/res/icons/clock2.png b/src/qt/res/icons/clock2.png index 187a6efea944238a271e23d03a3a0c9c04093fa3..45d590253ac70597fd164ae7869941a9b46f9442 100644 GIT binary patch literal 10868 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 literal 18384 zcmeI4dpy(a|HtQ8NJ`|)Xq7{=lWjJ$oYIJHiK06)+c0Ju8z$~@sHi())qSTZCGJW| zbZ~B^XmxkI6UD71og}9s5`8y1=u_=+-;dw-_s8$|*dCAB-q-tjy{^yad0p50^VuIC zTfLSqRaezl1%W{7ZX_3P@n^i`JzZJ+*XUiQoA^V8P4ee}Kx%U&Z#mH3TwM^zZZF-( zkL%~@fv2z{t;tkYFwL45$rkqpfe4FvY%(Q+#svq{Lg`F!WEa*Dv>>tdF4JsAh|asstWhY!FG~lEJ)429ty5*_%!H;>F)3%`h|YL>F#^ zy_utAK(L>u7ucB&M~5k-b?Mm&?Y(U~zGA)^R9nR&*!~fy3coa3l@^PVYDA9B_m(F5>CBEcfRt(qP%uF)S=hw&cie!Hth{^fLPD~NTBeP)$ zYdGwCA}Zyxh8+{lm^d^l1x91gB56!6N3279SH})xaao)&)(?jKoc`g!;yLm3{5;jzYLa?*5WL06o=Bw#UDl3j-L4W}z zU*`LZ8_k8xr4c1c@k)duYPg%F( z)jLtkR??!rZvB*C&?jmVn;gxdNp_sQ*{3b{xrlwPQ4-C>&c%}{l4?ezNHzqGN`QUU z`sJ`bD?iHU-%j8^qde(9MgHS4;=*W5X&Y+NYNFSVO*pI&ZX7w9<`^no6F=DN=&5^s z()DW@(4GL3RDTBje_!f}$ihD71vNIV=3g<~h`+J9{tzACx@WE#G#VoDg98A_uPVV}cbZQzX^_MQ4ng&Y0D1Di9E>XN^Ck_y z(})-}8igjnfXzUK7oA6A__@%<*G!J&N`OF$nM{a)neQt7f2f?2`KX+ntSL9q6ZLbl zReXys{&fKR{PW01)Y+43~61fUFD`0EqNZhD$mh zKvsqe07QBy!zG;$AS=TK03tn<;gZe=kd@&A0FfTba7pI_$jWd5fJhHzxTNy|WM#Mj zK%|E5b2=|mvlaWtPB?bi1bi~OFADwR)z}zM0zL{ zm+F@XZfQ*MQ?_y9$7#13uI9?JrD z?{)f3*i@J@f59~m^TgkKmmq)3+53iFi8QH5bWNHWHorhl-g237_=WBH3YKuxSpR51 z)dj&=9;dhREnz6`M0p6bWwebm^tQWp!EXUkMX;=x2;Tw z^1sQyPOcOX^3ma`+S+`pSiWlv=+cLn`N90fj0!&nu1excd@4zj}pGW4AzaZnv7pw02NQ zCg_44#hk6)H}eo-izk1ReSI5yW7pU@UgjQ zj^$5_ZqKh_@ku411xLaM#Wt^@^s0P;vHs*q~(h3M=2?`+4K*J#$DmI?RJi`#2)^ zpaesb@$~m{wpFCJqq;nKo@<8YGL^~~QP^d}Ptwoycw9=<_vfEiZd16c#XB%FUxhb| z2WpwMbL^e2NLxhs*AWBk?M)S*bx=iayDvGr4Qvo_ z1m-5c*v+o)g$L|kY*wjzVz1MO((J_aV@iX>cjE!`dsU9j#HDXcOwNojClMWf-y=s1 z=~Z{{`!%yU0PfIqN$$ylN`2niw_Ybxnp6ZnW+ERrOp8w>mxBCdz?gANwwL?#M;A^xA3& zGN|1duS>KU?(N-)J`?6Ep=Z_jd3 zqP$JbLM=4D=Z zcQBRbR2Y^Plr7IZ$zr%`r*>{_p_H{N)xErXm~Y+sY_5BBM%tP43M$^C=L|;q9q-;X z6g_Yv)yZw$aW)7aT*fu8J#AkP6Q+S4qQ-AIK~(P?B-oy;J4H`7;lr>!_l@57`u*V? z?{)Of*@b+KyJJnqtd|H)44ZfK=Zc-i14;W+a-Rs(=5}VS*>y{ACBOQ`ws5n`xwr!A z1?^4UivwLxK_hPS2i+jJ&DXCEHt(q!exRtbF6|x`Q&^_=FhLhjFxjcon=af&b<_|g zY4NWeCbUhXC}6|)Hp>RfZz~xXKzy7i$p)Ya-DVR z@8_FBOmdyBzUXu|RNAd4IIEboHqXh)b zQdloN#=#A#Y#lbF!|Ct+RQ}_hO8;$&f>)_7jcrOb4uo92+B+@B156gUXhtfHA8wv` zLFswgrGjSgpmA|l{j{dex9zl6<>Ufk@7k`MRr0T|Kkb3&?0chHpg)3A5dQ4#dhnRe z%!6$#s8jhoT*v5%C1K0;=7%ng=7tVTyO*=}RRd~Q=`I3e8QDsXon>&->*B?04O*CL zZl1x-Tc+wWFsBpd(R|d)st!5x;4Mcso;=O(4&e+3%^V`hUCYQwtBO+BKE8ysswm6r z=Vfm?%&{d0QwqZcAwiLx3dAOH9X_& z)vniN>l8_2WVME>es!he#a(S{`OnD9%Gosr54}XT&ii76HdqS{k~Zq$HyDLBT4Tev z?~IJ%6p<;`Lc5|^V;|GaCylPA{dG#u@##}{y8oYu@hkq!+-uud2Cdg$Z0igy&EpRv zHPxPYt)Foz(LpcRTggYupG zy-q-W?%PP{@fi5EWjSn!Q(oCwq1&2WM7y4|<#K|VUUz&|k?7#nJHDXj_nQ0lA%Q$5jo zhK0@@fl*6@rCm#wa)^H8nSfA2pj)7FTSQ_$0`k})&H`bi%Ve~+Q9{%pEZn!Q@N23W-lT2Uj0;5}XFUpqp3tTD9o z*n#S?`zDsj_XQgohJH;-7(kb0wPkiTl|HS-FWHQl)?1-8eCSleaAil%>Fd%HnBAYtQVv`6r2YRJeC&46#o6lQ2X?8K6fG8Iyf6*&X+SD z7=BXd+Yy`arX-=y9#0HZMBT(Wt|XfDX?7=Xyk9uF;PCr(mXA7DbwP4^PCYCj#jJN< zGJp{o@NR}IcKf||?prJ=wC>#HUJacp?pd&DRk8ih%N<(QIs22IRC_;sO+UQlkj`=6l!sQGa@!Dsi0rDQ zmxQ5Z#eIk!!|w`~c6r-fPgTsj94=Z$T;K(Uq(Z<(Dm7gNz2>3=B+#0*xdv!UY8_~M zA8vnvh4MhqOjkG4j@kR^QjCa6Olzlx})HE@$hjRK;fd zW1WG%`R(UbhUc;^I_^R7cjPp#)H|RwM{s2hXzH#&>`Tz%&ADw>OA7blA-fy;1#Vif z4{zl=&Aax3O^5+0a%&1xF2x8mww12;F}-&H744Hzi4VFqXnEM{{Z$fSKRZyNWurkhR`te4`mHGVhEZnOGgDlV{Q_}2`3hk11)iw=7<+Xl{zp<8((EcKQP32;^ z=Agb$YZg7 z#!a{_JBZW|v$Usm9C<9^W_(w54`=_eJB87RmqIaa*$7rNk*H_Bd-}hZ*jaiw@m|@16L`k}nB`Hg!h_WPWi@lJt zi|k7zg_KgX$om_*tNVHG<+(ra`@DbM=JT8JJLh}8=Q`)Q&bhA7b;`=ZkbnL5^&k+4 z-`Ggc2KWtRKRn#Px5TGtV-RT5-XJ@BmJQAy%MDnJJ{sRRubG|0y#+O@tB z<2Rane5a;$3S28(V121OM=Dx#3pQL`6c;GCG&FE5=qpaOVEOu>X~m^4(`|P)MeP!?rFc^ka1+%)K`|5ur+2%)io&Bh4@@a_V_pSBW9^!1hc>A4Yb)!;n-m43}sl`*6&wVa!CYfE8==Ws_pCx2ADkRJfoU;TO z=ExU(=v&OAdJE3$qt{(}d_ow~p&@m0Ymf?Vq(@ZRwAuT?J?i26{l}4>ir{r(zdfC{VwapkxSvbdNJ0p1M zzSV|Pv6`X zeK}8TJZYu3dIg1~&7HjS%bo;HW~G|?4-a877B(Ah4{U6=Hjtpr^9GaC5WeRf+*6L! zCkRhev$o!vI+XkRW>{ydQ`v0Mv{$+0O~1~EhS6z0Q_Xwz+?>qTpit zyQh9$0#AteeNrPZF;BU?>rnO7+{OLrQ^yR>_q$IQZawSdU+W(Zeb%j@d7nYMi9Atf zx(h?tG>bGC!4@^Zb04WO&j__*J90T<^u~%EU+5HqUO`J$n>lADYI7AOzzY=_ul)&n z5&bG54rXO83kE0CuT@@I=a)$ry!Xq@CjVH$8P&e`RcB0#noS%z?@Y(La$Av&j?@$# zQ59_3rN$jwB#z6vHfu>%QZZyb*eUciXRmsKjx&nm$f+(NhP#Y+lq^4AO16C+tULqv z(x`CLylhvd!Qy_i8~{*j7VOpPQ#PZJZE{V&B`IgC_CQhv0qHz6=$7`s4Z(2 z?A%qSv;Owz4len8WKCd(RhP2E_#2DVQ2ZKc?>jSgLFKAmQgJ43jMmVuy-0Wau`}ryS2?l~oZ=>BLJ79jW!&9rls?wD!KK z0QqyeH%U5sMf;i_DZ&lfd$WWiADF0WbL9J2+jEYM_*H^BbWSC-XU_&Jp54-|g$` zo?}Bl+}7S?Geo>PEOOcg_ITW`b~iIreFAsylHtQG#KDOeQ6n1qOi4=})dk{wZqu{l zTY4Xo&I=VrIyCS^y7BLq>AuY?TcWeRzs^ESXTy$&()}{;_B9E^9e0|$gBrmSSo^pw z>Q~{m<5bw9P~nvqG}F24;q!31M(A_7D@ZAN`WoZJ$n{J0gD~C1b2sTi!Y4i)I)02+ zvk;TU%eZXj8D)^{dEa&h9>cjXUN6LGnyd>Mlj3V~_c}Dhd%z|0YT0S!;I^C*>(1;0 z$dqJStN8x_GPWF!9!RJdpC z%A;R;4N^ax@5n_R$`p29Ok%>49?0Jl?{yvDd(BREt?rHp7}~rpQY)VDv<~8S#;G<2 zmr>n|lq+P2QhBI5NoEyVlDo~7u-h(oZru-Fv{<*kNMs0^MX0F_BfacBv*Ddd=Z&iI zlxt@eYl_<*!^KOlP!rY`r%zP8m|{gX;1#(TlfhFpuVt@8Cu+n3$0QkMNdwa2GKWEl zAFpl9S4lgr9^xRC>3+m@Sb1D;c7wQ@;gEpUqNY@B<@F~Kv3wmb`K~@VF}{Ef443X{ zbazVyU)XyxGf3ymF|nOiZRL664%W1G9)qK}fpzzYDeFwS+mOwml3&i$VA4aJXIO(J zB2<1XFElI;vgtzNFIItD3Q{tmokwNsvyOOP!uXVs+SYZrs6~)JEMe5@O2^ zb9a}G9xaZg(f5Yxec{^jEb&C$E>Dr|OJPMsp6ndM=e*)%18J)1_0Q+r#y4{2ipe{6 zMk;>_wue=wCA~>VcTA6x8J{;VQ94nAFq1P_LQ3&(j(QPT5L<3)H+;Nx&BiZ%AH6>$ z#zY9ZJ*6NQGHa)XB90H`c7()Q>x7q|+4OR!b-z}ORhUix=CC@AwD2J*>ZVXRn*%o| zEw}EAed~f99EqRmp?DunyKumfD|#?yNbb1NJ?;79VppNe#GTCITBI@w@D`Hbs~ZInt5evzI}t$ROPUY`0&GYc7d>)IfD?%b`R z91e^5giR~hzH@o3ZL``&~J8pW30J2{Z7S*EF3dG`{v7jEem()9VlW=~hi<(axc zO~=Bc0rgK^VJdl|;g4vLsX|W^mQ^~q?D&=XFKeG?^V=>u(&}vRnat?z4sraa3Ux8N z3gd{ovEb-V4S{58@5f>0(S?4OLn2oxw7|Eag;!&~1`9c~ai&y!cG?gw(7q^4TcB;P z3P?yWhH*a%YT~1ejuae^qNz^j7H$t2w~kBFr=O$_3@)|0$!nnezBD+;hg`K+oh;BP zskGurR^ZB&m4lpZQ5HWoZ>7O!KsV#$pZM&zXQbrohl3`syN^Wjo=Dd;w+Gd#Y&>=2 zjo46IR>%9qW$zf*olQ%aXCW~v3(zi$hG5%_rpI|+gk#S;?u1`QPm0^lBdc1{6u>X> z$LHz|lwAbTx9pmlUYY0Z&X{x9)_arN`?g(ip(cz|DmfZxQ<8+`{=Lsk zrq9%O5%2oEXgbnWxxW}LaMj|mp>gPZre~U-A#d)adX5q!G4Nhp8#P8V77p#bEpxlm zf?S${ys6byZoxHGqMr8=v zJ(2N5S+xX{kb!WXvh| z=A+Z8g2G2qQTfvbZ=S|QS6|*SW-FZXjL_u%G!v%YqSAtXt`ZSS&TvVP9?j1`{p55P zs(4AWe?o@qu&k~}vYDe?6mT8Yg5^@;-L~NN~J1VSax`}LI-aVa|4`cdtZXUl{jQ(=@43u!octgW$ zjp{+AGT&_7>jMExN6voaL)0g|JBZ}3$#%FF3xBEmRyVF>YoEaaE?@P7o!I(?&WKXx z6F%X7pU%Te9l_iN)~{!FlEk*HIqUA&mEZ@C(mzdxN=43RSG=jFEQJg% zEose7;x;>ET-}H++@W8cB3vo0rwQ|RwRJ4fmVJ5fu0QW=Qg~HF)M#)2Ig>5FK#WqQ z7wzuXq71LSJroizWz6lk|9-l=&N9p`dgI)Sn+{%=n`fEQ1?VQ!*+Bj(W!8H9*jPzS zt+H@*=>wEwdV=2?qrpOdg^pmZ(uufK-d5rEO~Pj39Vz#BA~4LlDe?s_n}{|bpf>OB8O`2jp(M5L7f>q#cJ?q`t*ZTD1pmGS@=;#v8xq=m z`6g@9>Pu~jLTFg@Xrs*>-$S@Sg|^h2lDvH_Pm&KO$`75i@$HmvFR`hO>m(g8kz9X0 zOzGw9OTO3JoVPE_9%V)zor`+DCjYZP;Z2+E8_S`%HoeSbN!0?vDqLv@H+%bcJ<}gZGw_ZTA|zGJhOv?=ie%4p;I>`}xxh#k9GO=a3sb znJ**l@~-aceHop!!KOTZDNg@T%@+;chtM=`$)pfkW8YUi54p@ePVZxDl3NdIrr@-j z5lE7URdkEMXN>Wh)kx)f#JuZpYS;V2BFXbSbD(WqP&4mj^N($?@k6>g^8$yHHQf|<}*?6 zKP`Z;xp$V=?ovOWiEuh!3jzsAP=I>_dvh}^flgDv5$Sl6LI8~c+$(@UYMKEI9Kn;s z0^>>U6fbqi>+)&{m_k&C96*`F%o(~Q4~kKc56L#j!j2H+Nx%>xni}iX0b7V%Tpak9(rCZ2V6yc6e)#)c3#J`#eWPeYV$ywm z2qb+!k{4^|&rTUsU*^v~eVHV-Xl2|~B3Tg_)QabyZ48agt-jl^)96m2F;*Vg0^`U*}~d=9T%w>d^_l?BI;`)FFUGfk+`@aRe9-}g#j~;w1Z=?N=jHH3<^`hek1&jru*2@=~Q(H zdv3t&l&<(=tIdHXNyM>m-{~-HIt0oNU_qdzt?}p^8@;wMcaqvPxtY(^s&SrA`w`B&hvZV z?@TtpUd3ej1RDQEQ2&Bc12S)Jjx_>o={|u!`L`u`ufDCOhe}!5I>6wSCJwZS)wM=g zSpdY9IRx^&s-*l*L->z-%6Aqfoy_vb`H-~Tfu*eu(Pr<_V5?tSC|Fk)46Ha5SoT|0 z@A>T*{5?qQlKsOqxjNV1cFR8qj*0Ul{Yz*B51f}f2{;OT+XwzEWD*gj48tptpeUdd zvfC&Oic=;jK`~?%G6_$Fqev*sZwLJ!g{=ISAp^TLhFyjTB`ge%MIxXuWp)|?#OY?UfR#A?_5qlIkR#_X-i)|bJcQb<0(E%jep-yh(9vR~<(^uIL!8MbPzOJ@WE z+q?(M(%z{P}tqlAv@IR~T|14eWf86Ea%xPn+Im@) z@u1s&>upZI;8)#ls*LxzpC7T%_t}ZL_m*1D%PBi%b>9Hp9=~NZ@_CC(wLjOO=oDZ3 z@Y);Odzy33=?THWx7t@UUbKgZX^fi6ip5Ay7c@nAHlWrZI*v7GZHVWM z{qYGi3;pS%5Zdgilei+lOTBZ9@k?`^71*PB$YNU$S0j<<8FU)4v%DuL>S2^;5t3-& zXWMx30;*@+Wqf-|O0*~SNpZkJ!-kYTm-w96ThUbN4fPy&;Dq;?7Ob!UO0=C{`Ji|< za_^2RX#(^9&aT~P&b#O9apj&`%7~=WJJt2e=%hjyrR531Pb8l7l&I-Sf>=8fI!r~R ze_m7N;mmngWb_T{qfC2^LWOjU+Ws}zwlNoJ&b#YIhsJ}rJlq~E^pQnEyXTfl5XJS2R(L+_)ThMGb}Q)_Q)vWDWx02$nrizUb?!%E;K{${FIxwqS{(dTVpnh+$OyU7bC}c*i zDgJjvYi1Cu56n1RFf= zQz9;BL?en3M-5Gl%fW$BU^FO@N+2EKlR8nPP%4x}3O_UCi2JhxLpfnGN5=l-e50d3 zIkZIT77HPGhxC(5NkF^^#QA{|VT_mqy2V1LGW}C$FXi(_lk-6&rRTGA2W9-v$dsO8 z+0arL&JZ0sSDLFBWJ`tO0HH9-X?T_Syhn(3bycn^d-SY8zJM!?lYC9b!6l>l9*qVv z*iz6*sf1P{mOu(1P-(WdG!h<*r_k{DF+qlV!eTImTs|-UeGIBH29X>9Nr`qeTgV)Z zF{URx2DE>;Y$^M1MH$<7OdKwU#uJL8*-|HdG&=&si3AaJ+-T#No+GP@<|>R5ilJ$N zPPTO1r<%v8hE^JFo8pY<4)AL?Ljo_C)9-oJ%5M+4lC~SX&;K z!=Z3VR4|-31d+)cEB`1oL&%9y?v{6~ zcSP}rYLbX8mVn9~=ZJZ~#1CuY`%?aK4W%n@Bxq3mg=ztNsO~{^|D(3iH8b3wrL3b-F+=_BiFoLRBPc)L zNyob3(#6Qqv2M6@RJl;VmpT#OjRtETqf*}O3}1@6X1KzKF9V}k z3_f(tlqjzR1R}&_NCfwMQn~oE$}ygI%Hd>vE^Qv&cfFPSHT*!Q2UKK7F5M)z@3z-khtHK2Xf^4dAA@hNGRk&b4kWCdX zWIiyj3Kt9rvZ=y_%m?OG;er7{HdVNg`M|s?TreQWrV1A_ADCB#3kC$)RN+GA1M{kI z!GIu}DqP5XU|tn27!YJrg$tPv%&Wo$1A=TK;?f#@;1(1>Pua#nkJIjADWIox0W@c> z9}@sp&H#X=G82%24U zPI&28hRM-Z-`=B-TAOuW|ETWVS<#uKu){_sp}$TPY|-*uMrpC!#`b#@v`%bIK6Cu) zo?H4y5;al9`!1X`*@q_fEW4hsJtrrvxWl5f;fC(c3l&ALauX^F`uc9|sWG8cP+JE} zTH|vYdJ}Sc`)7NF3JyUP2ND38=7Zzc z43|3GHEgvA-IaGc-s_UTZy#z~()G8mxceefdse+rlz&y`zLb1YpQS;1&6^X($RBq{ z?Qq`7Baxk3cITFPyvWi!tyXcY(K=~nvf-2>{8csEvjY@=ja&ZS10|I6$Nw-Wa_;sw%e$rBX4Y4hP__5LKBlbnnWb0*zhHw^*rvt1 zChyqN+J2KB=Aji*`=_bi9QCViiF?nT7Ot7M&b*KG;GT}>xWn6Bo<2?vN^UCy%OoMp zX7l##!6q)ZSLw=3SqIIZ8OE$mC$A0(wvyLT)mhs8UldM~6{$Ev>~tOWvSO2Z962$b;JTN7Ls|5811=6xBVg zF+AoAj>Gyqm$fh7Xa(y9=MTI-Ai#+1T2X8Kyy-hJr4}-+tPGDDJIiMd?m4aYPf9$i zfB>DWr#Ng z>(cX9MY6877nG4@__k1YFNWdFs_hG!L(43BBMu}YN%ml`?o-K2~ zaP+k3x2?3)zq+AqFxbs}gXimF@yt_Azow=itM0H#QzWOgy#1DbIP~;nEJ~C>{9ZF{ zT2FBOeeMOV;ANK&W!lvhXn$E`#i(mYo8#BFwWj1y{dUiYw?>#AeeSB$+M6;me(+r> z?E5a!%}Mih-s3I5VUD4<^x$V^-`RZ2qd6sgRjl;}=MK^h*B@5a?Poao_66R5lzDr? zuDuH~+io@DF<~i*H@9tC**u+mu>bj8!|Hj>g9`ikHo*&Sm6Uh39Lj9-bT*Rv7czai zfYpN7Enlw6D0KIdM^HjVU-z)HC*yc6`fqgVopuYpIedQeYl2nwoy0@7@({=Nx+JTD zh^XwhY zxwwPp@Drt1v3t)Zv$C5!duO*vqD|s~@~9TGnKLW1_pQ42Ds+-YE+Hr01J}47sJYRQ z!sOZFOibLHZ}V_ClP}R5sp6mYf|hl}FwLKdnhXneoZCDxLrN<;xqn+}zyw9+5GaE3(BCr#CO%0Jt)v!(3b(RL1W zU^S(vLxL7P-^1iqxWyj5Ud^*E&FOI8Fl9r|iSs`Y%CI($H=_Q)2C3KcvhtEq&}?d& zW}m9&t*My`;Apw@+NXaAnGchL(sDI}>YU4TMSoh=#@5Yxqu0$jy^DeUr9O|;~7`}|AN1 zU)Z%Sdi#b6(8yS`jXIfY?xkoHVgb^P%YU`W4k;>{UcP7oj@|wl^bg64T@`^@*XI-x zI2m&@%a{1fp~r%zA5T3M7HIR`qmqO9zNWjMEM0Ibov~WCu5KU3n*PjOLdsdY#RL6yxiw1p^X3YeN0D4of3>P)4wCevvWG=g95U zor{)+hUA?+V~kO!PpCI-LX~JFR!UR1&!Ds@biNIKZi=4L)Ng^>m1QU=SKe{?5s$I> zc2Nq6mK&CQ#n(Avx54i@g9qAurE=8SN4dwRaCf$|qn4avokkVNQ!RZr>U4i0@<{ES z(!L_dB7|}dDAfy^rRe2pi^5*te<;Pd{rZ>2;f107sOw(dM;T7z5|g`&Ybq*Rim#Hi z%a=5UbIn4pGsf5a)sc9qD{_tbN%O48TI$cJ>m~R1bZKZs(>mlceyMZa`PF7io5kGQ zaYvp8B!}UeF)niR=BY~q6=F@ZjuV$!4myN8bhpuG`&eSsqsCoTuW0p+RqNK{qINR{ zQ_r?C(zd@kn8o}<(CqpmCf@0qXXhGT<%PiHeBb0agO0W3&-6Nyy;G)!g0?=_s_J42 z?-u81_NTt3{AAR7z?b59Tj5!CN-du-G5dP$_}~Ti8$$DR3rz}BC!YO2{YHV~xZp{_ zti~WJz&ajs(R8Vepv@pL+@gC%<9zNCqcDb`mE9T3MUke ze~s_1nE36Xm+_?H_p(KeUve)#nrfMFTyJmnS@iOz!v>WX+oO&z z(V8^v7}cVx2@=zFelwQaJIX;K$vc~#JY_{ZY)20`R*!uY~tRnCQ;%wDsyiCn|{=F)R}Ry@9- zP+KoA>nw~Ocrrx@-9d1YZ>BlEeBss{8#=y4-GX6w9WyzY15fWn-Gnla?Mw%jG5~&z7Hzvc3nX!f@6hbN`Tb4@N@W@&s zc@oMRBBauy5L&cQy!X&kJ^SzZyzlS*>v4bX8TWO*=Xb0uPj-T4wdu!RnC)Bb&giYTFu3g*s%zK-$d$#Ot5jC?$tGWK* z6R|^Xa*>0d3YOlRYP>!lI#SJcHuHX1J$C-l`QdE48oy^@4e;8i9$7~9v@NkJ~rmEJPE#eP;J$HjjVHbsW?w* zKnDAm8Gc`;XtrW3(ttE^jo9QfmTz~&veHRrgGEBM@r|j ztS#z8!!r=`yOw^?XMC=%6PIo|k*TXP9yz!vaYf|Q)ExoxZFkIZdkgk-OzUwIs)BDR zzQGH*M?H0j>Q%%Fes+nsZ+x>_M+&x#bx60$icS!}alUh+6{}ptrX2b}&fRZ8)j1V& zmZG&~vX>k>G%iKl1z>7r{ zGg6tPe%i>+iixWO6R|r?Sa+KXR+vqfb-8cZb83d&T_4*Np;kUcXoaN~y?tlXZG35_ zf`Bw`mN$UOJ3)tcOGEQcH?;H~b}VahZ3$11vpz(CQzhEO*t(*1E z;Wo&N#d;A}l12xquU6$X=_k0+E8~exlC#fUN-vdLt?@0L%^uz5RFNE!o)R`#U3R4# zDs|@WPA{@+Yt4secu}!}o}a@EE|vG$PNu1wXur};GS=z5X8)2M<8%*FjAB-@M-2z) zYny55CHab%LK>r(CfDbt`PpZSwp3&l?rfL$L^Id>u-PZGJGveR`7foTFJIs?(j+tG zGW*vQlpbV=lXO>{FK@p`af))QJY`bfcC#lnhg@ZdEQAazi?u0Mx!rnEok$u^D}NgL zTv?_K-+96^Omv@p!w!Y+6=lIi57bv$Ana?yUaex;o6JP|Eopa9X+*qjt_Va-K04;v zKDAHvWhU3-i0ZJEYjn-+>Rl&FR(UzsE645330G`F-|04Stzc-|oUCe;A)NTRRjy~c zjVe6y^zxHtxw#8z`WHTy6CBst>^{ix)(%KaQ^Dy``|4wxPs%te$t*8uw6&8@IHP@hp#OPJ6zFpKom&A(L1T<{D>zC5>Q(4dXbz1suFOY8$Hjx%cx@|n_6%{rxQ0L3H+a=*D z>(c4Vp}qQyO1e>|V;uBjTLtOHV8DK;QAZ{_ZqlRDwds@aLB6dG0Xm1HOWz8*$dsKB zSA!*TOYGo}k~Q5R`Ug2R+Q+!>JM?0!?;uA&KGBZ)b&j96mLR4NXCftGFZAbl?ID&0xB1G(- zN1&r*=7#-eV{+}D3PQ{3$PT`NF!zLsEXjMKT}rE{O{&H&M`X?NQTYLexDbVaeVqes zqxLo1ZTF&FnNL^&Ty5Jpe`tApS^Uj$33f+etW*6tgkD8nPe7~C>ZF(@lbK0}Y zYWR{x{8$!g&9HdVqcNoU{qg9g0O2pPs939W6k}@L;e386h}*s$8*jiWwiN6{hn25S z>Nu(pc~&m*dFMf>$eUiI#Ol^#QNYS5WCiS_sEzECmiUZjtiO=?0m*q-*Es^9L>2W( z3A8PC2;0KDeAaqnx+{p7z4b5zeT^q@3l&u(~8n=hD?@Z~6%}G_Tyy!r7>le=0=k&Br5_ z4(&66q3+U+Z1<-(BD!lf?Z19pY$B=LkV{p9d&`CGKt?i7+jy{&IKp?un8Z)ZNXZw; zOe?|B&@ueVgxvz`m(57rH-~Bsn4TwnIY#Es-AWa_&G(*C(zT__T*LPf(Ib9E=MpAB zkzT_%73kE0rN-rDh@aQh4a*G~r1xypbK?8S?)>u_*$YucnMZ{}1$9-sMN465+x|DP z>+(Bochm{bE{7G+Zk%tL?#_djeI^i84_`kbB3XAWH^_47YZJ^|>2TouhNh1r6AI5Q zOe3SDS+?nQape+8bGaU9u2Vwn^MDneTJ{~OjvrvT0V4YnRCKp@Oc{L+N2cv+Cw!F2 zO(m^Q37EMx5O29%Y*nl97mT{3OyX2%F}GTF&175Kx|JVGy9&pp)g-kn>bra{X~m)Vl&9Lo3k>xiE#tC9fk!eN4U1n*&qz)B56U_=)TmEbmnz3)C$WlvJjZS%{vUAt89%pm1(y;Ut zqCrrmOQ4IK;ulA8#>!GVft-kQ@_r-3p_gF~YLVi_mvdp zdLC33&dG({!et7Lgd;Bu`3~y#P0zhm9js1%_GJ2D(NNw~{sy%%IqwFTa)C_nIicf3 zbtu>2*gCf}XhAg#!cTd5Gqs7l)mL+k9 zg0+Io=OrzS=l2MHIz2MqZi#`->c{$g^vy{9@a^pNdiwdJ zm6G{BGLnhS14dd^w-xo5Y0&bdxy#*mbX>iDEp?qR-SN$D79dCW;Zk4BWzi?0vSCsn3~S+w@L7yMJ5wv)c_a z)Fvq=BUXcl>H;JIR$q^|?k$|h>;O&rQ-j8 zB)(G0j~;fMY3UfUr)FPb&)e>rcX{zr^3fr){vMSysYY=b?aEg7{P&MceI<*oG+{TE z-mBAcH!rEYRRzWFp*jq!=KJ&8Q>YaA1kI5=g$6g7C@zt@!W_AFD_((AqtSj& z?foT=>WgGj!0z*+*0NK5E5>JKtZy?6=E^izD?bR1y{e)rqe@rXY?Id=hRKHA?(?-u z^^Qc*FQg_#y`uXll3YdiDBiv)(Crs7R(2!VN^{_&c3kJy zc$OTha({qUv>ZL|k)-hI-L=duuiwF{%UJX#CFkbxE*mjXsWtb{+P_=B7ju{M&@L%5 zTeL%odB{$a7;i7j_aRX*8&y}G7vP@a)p2$ww|~u^0hvhwKBBs{Zqk8}H|I8Ip3}U& zBqO$2^S0&}k;lriq7njR+d+p^4j(kCbxbd%Xi_G;WOzWe;k~U9arEfbn+>6l6SmKE z$%L9%^qfYpN{i!qZXJ%JXJj3TPgUyLw^Uql-v^hyOP7{k^`p7jC8r&*zgHRpaV?@n z>>tlSHPyQfq2=2KxZ))!Mo;ByXvoc+jhCN~V%5SE-l{&!X}ou$m#6o~Pw+K7Er{spJlof+cg(EsPLXvH1D~5x^0KdVdFIPu;Vnj|$ds(;%r~q) zi?ahh*E(!cmtTsYC>XX^RUL{M%@4(2*Lpu4#yqq|EHnbjBy|#|ng=;@F)Gm8nQCpmA z&uP-h+?)2!;<9gL(7AqQ@RPdHy12P93`|Xh^V$9Rl1}y0R&%xxh@2`7{H^O^XN#vW z{Pf9Gh9{sO;>QGk3qv5LYeSf1iZ8%{dIH`we>2!*^>rAOMm2+N!`dP3m{x!fZ9^Cf za0=T@qJ;TUa8%e@b8*uUJV@XNaLCXQKe|5~A7Tbu;KhUg^M(;H=mLb}YX)<%bAVbg zSO65GkI_fMtwU%*XqdS;)RaZ_!aEYyf29DQ%wRqo4ik?+1P2G}2OH=!Sl$Q}4u?Y^ z(Fime4kF;}P=5|N1n$q);884c5CArXMPqVk41Xw(lkCX|evwN9KPxB!st!&V=id$&_5!nly5j@Ad9|$p;8b49qVOa-f9( zbQc0>*ME@|g+~2G>iP%LZ%bp5+m1m6sTXs=TLE}5eqavCymAL!Ss+{(=M@q?kT<;5 zp9W4A{axhpU1kO|0&5(JM4)(|-yyDl2?19N-iif~IRF8?L2e|<2#!R-Q5X^mhc__5 zV~}v9G5#yzH#CDqVle1tFkWt;ypS%~S02=@Qac)mlwv8-cp zf*CAddzQWDZh*r1Yo0#>e`9h4_bN7r6-xXYr+$Mo1tV`~hu;9|GFYKM*mnW~7M~Ww zL#Hil9Z={(6UUP&i))RtumGqFIRxXpD5U*CL->z-$~P7^!;2G4W&!KG!KG~mTgTg@ zp$@;aP^gs^6kKsw=<2Ukt@Gzj2M?L-zLuz@xy| zec-QLHU!%w*2s_w#~~>I90y>G;bbJ%0FE;R(1u8?kr9^c_3KIhM=l%vt;^tUjpLOe z+5nG4;n84K8u7~T|G{N4%F7UiAyeQO0A~cpkuipFV+@%LM+0PIPYf0?#-SHm&_B!a z-@E)Lt>XW|Wx$gPkPVE;a8CmRG8{t&_eq=)4hsj6o>Vdhhe4r{i~ax4T($vEBMXi2 z@A8TU`>6pOg(9Jmc&stlVSmY}DS~&z`=ww_d556il(Z@Dkc21lwkoGUCX-GBSidgy zUs~Uv;C|3w=$wqdRsRvTsBOhyhJxF?563>(|1Zt|0dSGQmPP@$&A+t$BV;iwKb(X? zmlwyt6E=8YM|?Z6e{FPNhW?v>UmNIu(*zXyuaSQg-+#mPZ@B(Z1pX2D-_`YRxc*TD z{t@`!)%AZCF7fa0`~ZLObRP`9(Q`3!eG9$~6!zR?Lx9ZluH2e}6mUe0xxtkUfk?>m zZazpxmLfPP!XesOi#!#Okj1N?g*+I8K=@A)3F}B9{jW}zY!N^$v%Ye&@CI;rS!a~M z4uMr=1cIb-o*-JJY@Mu@CVA>{%DWF^U-~Fx?;i{trzh78)`ky~+8@mJUg=@yysx(Y z)W0@oaz5OaKk$L?c`Jm(6>XBu3$ejh_s)r%@>PH7@A1%Pej)#Oi*UbGyIigR(kg#k zrLdsqC8TP&+F|WjSJ)RFi&ILFRAv>5XNhVQi%oS}zsf zR5qI7x>9ZEYCyb_L-1LA7C^T7=N7<_150Qq-e!B$H zAq&^LsFvXKHE+XA_0nvswJfv(p#~=+Mo?N^MPi4EW=$_L4_~;OJf_-TBOA@RrPLBZEtyrBp?ixIx?;tlX#U8l+@Y--{ptS z9pjtZRxQkd*R@c+(1s>1;m4b~MSLGegCu<->M~oX7QO;Q^d~|-JL@thiuek}Lf&e~ z)TPT2ASn*-QGybjoMc2-^i0^kgu=DZF!^`1HVl~64pPs6*-bYQa bispsi`EctiWoXLa0)`N+Hxr61J)-^xkDp=D literal 17774 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 diff --git a/src/qt/res/icons/configure.png b/src/qt/res/icons/configure.png index c9c24e1f2b264e75a475aa3a1ad9b290183e51ea..18e47efca838619884a10ad97fde925c7ac2ad6a 100644 GIT binary patch literal 12056 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 sH?ZvOxGa)MAA2-{~z$B0Rd2UF#rGn literal 19049 zcmeI3XH-+$w#Rou7f_mjf*6_<4JouFLZk@<0TEG(B7|fEQAh#_9WlX%6j5xTctC74 z3)lrAV(^Hdz&R*QB=&PfML7y82zLV(jGA%oc=vsHZzLmauDSkmt^J#8&As=Bz0J$h zMRD5fX#fByl3bmea9LcIaNW>GwoOj!rA5g}k0jc%*gUsbDzpiyo0d@ViD9!y6toaUMs z4K7dg^r0lKqu{A}i-^-~;t5cINRUlN#79QZS%i37y@|L4=>K>#N)Iv7g}u&J&whMB zgrA2O!jTaTA}r0UkQ9tL4q=Tq!&u^RSc?S+EE;2lLgP^w3nUstK;sE$4C3=kk2nqb zXA?~gC3rhIe;y99Z1uv~Y$gGPii?Xgi!(Q4M2Dd;csw43#-gxTB-8`RN}#jJ@klyL ze=^9II8Gpo5=~>WX$(4IJT5te5yQ6C(;FY?>+ADzMKZq*L}z_w2T?@DlbI-t85;F7 z5tZ^)!;FcJn3x)sf&wGJNRZBEK|0J&b)1b?Z)D_8 zhi0)C$3h4`BmJq8<&(e!QQjbn5fe=T7so<}qW`m_XVXHzCFi?HD;#ej&C}GLBe1D4u zI+58Raa;+lL?p(-2ZJY=n-eV1NHmUsMo$Sc*;6Qn2ZKrrP52T6KOO^X=>tiz)&%qK zVod2N90S@vR5F|VkD^TNJ0%X4LI`Cla4^ZK5VI$jsBgiPy+y7pg7!*?b3pQPd2DyD>!>0uz1i28D5UmE@|W$vF< zz)3LwQRaSiHu-;$xyhaQeNFsQ%73h(Hsco(1gQQ(wSYWP_n@utL)*7CGuhv7ypBf1 zO!T+LqM;WGGyeTqI@K*K^%pIj>K2xMQ?8)X*hK8-(S(|(sK&2$CQrr7p$l`6Xk}?> zZfS!OZWdN}(c-}fKPMV=&SZ_B2{2gPXOXbyr%L}{DyMipD<_jRlx_3`RCgq{Wqfu#S#x91Vpqc#wD7MkXMXL2#9D?j7u~hA+H#h5D?L( z7?)^1LS8X0At0hnF)q=3guG&0LO?{DVqBv62zkZ0gn)=P#kfTC5%P+02>}spigAhN zBjgq15&|OH6yp-jN60J2B?LsYDaIw5kC0c4O9+T)Q;bVAA0e+8mkqD_&w zrhR+h7NkQ@*~USS)5@w|9)KRjMNnM5Jpdrl5PGC{BLI9DgMR-705NC)cpeM@gj@j7 zVB`eVI|IOU63NNlC%)^&!KAY@SIqf+QMCitp+Unq4Pm-PCpxgzUR6zswCpB!CYHor zy}u|p$8Y~-pG-s3*|BH6eA<#T0W_>S=X#J6nm6#aNIw9x4Bqs@3uD!GTu7$*YtdN z^3pK^-(ZL!kPz4k0tLFk2`V#m-md{w5fp8BrljYEd;KSQ${%HzbI`LjrIKInXToMftvcIL*TSAl zTa;1ZJ~_I@$FH6{1vG}->vLW4_PK+qKr?v1zFh)|^EXEd^U6}~;w`}?)4jl+O3AZ^ z)o;M4rUsc@{|8H!`@3;MdH#gpIov_sG=4Qg6lG z(5m#12|l#B0@EsStW*-G{N9s4{7LGf#p^3E?=}N-xYpdB<;ey09cR>ZU?b*FW(*h> z#tD*EnFh+;lZw}S(s1G2Xn(QHk!`A+zP@W_f|ZqT4m6+bXkU5G=t!3GrQ}0lhN^|~ zOp>$P%O-3;s;yEXv*C$+mgycKZbw$t-Rq;Z+OhyslSwvIDO}Vt|FC@$o=ZH_BC(c9 zF$?Ork|W#F7ToP4_i)h?TR>3die6iBtYOSaqXM197*}gr{K8KutR9Ffw;u-*5@H-^0`w?gL{e z5#8eE+qYE)n#^i z*-#hA?P%1vEvh?_uB>#BXggBEuiEw=UQ3T6DT4j3HROvCkKF5Z*gn zy+9UH?1!=5H7aDlwrnctM@Qi$?rFULZH2_Le8b?24<2jWd)&W?%yZt@*WCO>KG59A z&MYWgW~8f-WQpeAid$C2)4cZK@?mWQ9%HB4^V6Eyd}-W^Of7D+!pZ)fjT(tz&OqRB zGd8?(w&sJUmvGRa(^&dlg$oRM*<6O!>J6%|X|pn8%nMa>f?DRvwM8sR*mONxB2;U2 z@1lLEvrXwhnAYkl&L)q%7y()kAPC~k?m6BJ{I={UyTYxQw3gB_U*F{P9WR%z#iV>W zSb)~*B*Xe^)w`U1dnmOVH~HOBKiH;LVRgT3lV(=@!$0O-ou9VNX2Ia?bf9-yLXU%> zQ-MG7>0`aivfcaPzKBCzDboBok?+g%ln^hnW&oq^iJdOP5@UAx-ce;+&pK7dCh(u< z;-Wt|tm2of7?gZ};p(~Cwta2^tpukFd4b5GB;9TmVov^ugi@`G(ZNi3KgLZTc6pA7K}8;DdmQ&i1B1~LQC7o>&>V(Gf2gY= z1Ro2DRbg%ckDi9*#$Q5I*mh*uA&|hd+3OnJt6cctbijb_3l0 z^`(6@wV;70)ANr4Dy8@MSwAa&V`O?4R$CbV`e{AiT0O?MqSw@+dvn^=^m0Q;;NhI_ zu#9;&1s3J>Ja2JIcloXhn5P%3OT3Tdo>V$+5xJCaH`8!qywvN%yrGqQq+q)xt;-&& zNx2|GJB@?dUYU|&`8{hTE4h80D+_{?-ez|MF${`~Zw?I2EesPRabE_eDeB*fbTtd! z{X~H7fuF-fw3ls)Bwwzt=#;Hq%k1xBmYN=}a*p4A)GnJh^wgk2@f>(mE5qq2J*#Cf z*pN$Fv!P0*wiZlCzHeHgko(^8wpTYvt+B_57sc(r<#BU5`A_$xT6&|EOL+G(lG1r4 zpFWkKn*(aHz=N_qd`#;4@?8Z!br~`6LR6AJ|NKjKkoK`rI_AoQgOb;e`xKA|Ul}R& zDAY*fh_A2I8z^*3hG+Yi3kExiuIF0np8QmLgAu8!S>U}sWmeJ4M&4oN{%-AyhFP;= zR&rjHKZyv3ZV%Vo&P_YoH8Rl8Ge1?HSaHrclq|d6tkrz4G(7vsz~*^->^P2l-Yl!B zQ!F*MrL`RMo7Lgmfm))v6)5($(QJ@RPb~nJLLHAiap%lF5Zfmk*{&M~9VwR=uS|(&>lp3zu^95 zW`G>rMysOskn8MZwYRW&&jvO>1s#E`;DnvwM+GZ&_g3J*z~4*;R%sddTbczd>v}ir zo|)pJ)U&kJe2X`2A5eOb=w`9?x*LDL`VhaN;zfQ^w&|KrA%nKZ_$wKv(L1Qx_gvrp zz2ze`=R;2rFuGmxvt#cSOhzIO!=L>TP%{{%Olnb!f-4$V?45DJ;??1{H7fPVMC?A4 z_MTZVXn)EZl(ecfa&-18TIrk6KXpq~T*kt^Mud$i{E8~%LC8U0rdMVaoT7N?hn zc_hv*%!PF*=jyn*0c+}3>fXQf&Tw>W_2ZG=`92{p!;Lyz4C^%omTta7DF>+OLH9HG zD{}8jzlvPvtF#&TqywuTpo};L6daI}Kx-s2Es9{)tnME<3yWFoWvwY@+9*4-&n@ z^ItD-g8N?v7jsU#2Ntax_5S0kWRGd*fUKu)<%Znr*Pv7Mg3yG02P*aKI!?d3LaJRo z(igGNoA~^ydye`SGvQ&ZmIJr)PB+V>JRoqDj3(01CqrLX}iO2nH~IoV_eF=w-u zx{O3^-J!O}*1YPDrxNF1&Ap>$bMy7bzO<*9k$J&|5AG(KJdg;>(X|sKHIrjkuU+DH zJZk-}*46DPstPlb8IgBY0Dkq_kSmt~Ii0AEEoGR-ZKu~nn0v16NXp$z=roJ&aE;Ta zX?xuXc$Yg}eK;aJZ~2MYnjyovofmbMzMOSnGcG!INiJZd zd%x;KTEcLwL7|~%`F-OfUA}&qGm@JVD?GHGNv&2GX)SEf<3Bt{G_bEKu|0%(ScyD_ zEbzQY0G464Kdhg1VNqZFvq4Q zH@5VQ+Hj884pju}-zd>}4WhJGwi8caUT?b91(_2aE z{XI%=x|c4{hrdWO`xus5TXM?~)8VeT%JsaA%V7EGlxt=ue5S$d?wx9Ut_*X(yP^A{ zOC)mUVveO>re9XEOxxB|8w^dfwGK$a>{3nEGzPbrvUsJ(P+#I{ z1*$!##Ho3nnLM16yF|tp2dnfO+XqOz1-7Nn18zK!*{4(++N)BRmlfFun@0_B8_~RS z$*zDmRO6b|Iv7Eothyd2#3K7M)0nYjS7?~FJ)NaczoEV;O3Jn`bB847uN6&)3yb7hPN)8MPFp5Xxgm_W5N>>bkMivH%ecsXruq_5o^Bt(DBQRT juB{FG`P&p2(*oYkTpV?hUI*P^0sv{Tr_)J?;M9KuwWwnD diff --git a/src/qt/res/icons/debugwindow.png b/src/qt/res/icons/debugwindow.png index d64c7d7f66681b18fad234844cd7a2702d2d2647..aa71e8806a36d129583f60b400941ec7cb854bb4 100644 GIT binary patch literal 9692 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 literal 16882 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 diff --git a/src/qt/res/icons/edit.png b/src/qt/res/icons/edit.png index e0e76124dc07ef859b425b19d1c187f906897f75..8fba7c4f24d25e52ac81544aa6a762c2c8ac2a86 100644 GIT binary patch literal 10436 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 Y^MlL^SAH87C}fbi@eZRB1Gnh^0nX!iApigX literal 17612 zcmeI3d0Z3M7RM(c>>!J~AcP2tN;V)N2_YZ^3Mz^SPh3DkGC+_lkN^>s1eX@-g3D8= zD@ChusnWWj)xsdpy;@XUS{H)$S+zciS|w_PH(_^#`Lv(c_s4sm$>)>h+;e~D&i$Ty z&)obmB{9=Jv9}pz0|0=1R3twZ{??e@Ru=GQJx_2E{<4-w&Q<_`?O@Xz2W;9h0ssOx ziQ^KK3DHwILYagj5Xn+Nib^7fdjkMBSS1$-7l2A)3YaFA29a7$)RKr|Q4nbsBbpX1 z4+GQ1k@?x+%=~F_!u$n7wultWv*D^ZZ~zIY6cAOCOsRsS3L=^7Z#2`qJo3DveF0`;%#O4vo#B(TQCz z63+(y#myF_a$@-rUBkgv5Gh@$lyj)myu3V0o*zY)okpdz*=#D!m+I?FhI^0|3#Ced ziY!%(=?u~xhYu=**p@B>9PTa>~Rk`Fr1U<=$^6ry=)6ewlcaWYvZuXB~fbR#5&g_%}W0MUDvSSpg`DaLcDNJ($Ld!vDT zffD4Il<-O<)BWSuBF$Dc-~u{bnZpCFw*5iz1=B5~@%?ig%S3|~eZEcK&t=#0KG z`t(G`fcK9`pcMR}D1H0(i6atnQf1i^fs!Yd2+}~RT$;wE_BQtE*|VxRVX{nFHhfti z&yP#(uepz^W2JGTqza`#Dg>kWJh*`(7K=D6zf`{fKR-5^;p@vFGkyK(Q#IoWO&bCfaj74)_Fh(xvP&lZ zIDvnRa%cQL@`1<5O9!QB8>%x@N3Vf{C}gS1JV7=%DGgo|1MGE1-@V=$^+OplJeO*! z{+Z(cLLwA`-2W^M0)a^6FZA^%i%g{`CDorrX0e$fGQ7xXDXH*A5DEp|Y5r4bV3BET zQ(g1*9Jv0%wLs8O_vl>eM{T`prn7&7sg7pmbo3AKrNJ*M z-SpWd?dwKLXQNB|x{=aeWxQ0Zzw@M5?SK+sJL7djt=7sG`Bf^K5C(D@*|7%l`5bQ8mc z&IjSea3O%8n;0&1J_s*{3jqY(#BibWL3lA-2q5Sth6|k!!i(WT06{k~TkLg$0}M&`k^%Iv<1=!-W8XZeqC5`5?R)E(8#C6T^kh2jRtVA%LKp7%p@^ z2rq^U0R-K|aG~=-crjcEAm}EB3!M+bi{U~5K{qj6=zI`f3>N|jx{2XJ=Y#NKxDY_l zO$--0AA}dfg#dzXVz|)xAiNkZ1Q2u+6_-u#1Gk_Qe#$lvew;Qa@yuBGQCy-hGBz3j z^1a|kdY1ygn|Ap7F#zPy0N_b70C36yV7P4E{L>KtV6{JrKPgW2^V6*hGl#^xo()dC zJs~!Hsg?G5$lrta{zRhhDk-6#)@ql>X2v^5o!m<|3L1-xt1Ibl&#h8-j7_iI(=8fFytpR~A@442>zWpgT@b*tze@s)qeE6@; z0rAU2aZ&l}*G3cZk$j-Uis*#%Bx(4BHN}9lQwXWI@qBd7SM9{j7cc(JNR5YlD%{E| zW$TMdpcbeUa(G)fSZ}SL?ltl0Z|Ta3nq^rbgB$F&*iL1ro=t~FB{THHs;1=Po=1(Y zvU_Bigrfv3D?Ko%48KqFHMAJ2BZVBEY3pNg6v)F{TKukVwLD;1gWve5DO^+h74DW5 z7w8IEaoC|vXCmrz}pE@8@Vfp!VI_pP$h(cV2;{8I563fi*j&;OE>>69CU$M~p z+zvCb*~(>2Gd+yz-#zA0^?PdC=e5+kXufz`lQe5ouzh`+<}sl`;f*I)s>kVRdO$z7 zq*m>4GT@iiENBB{uXUTWeyaI_@Erbm3K0*gS3Pq-w#UvG`(|d@OL55Mvz&wDG?%@d zbiszgIq%GMx#Y{!c{gjP%vv(h-r@NmKq|FznJL2v@ zmMq)rGWWP`csIr(hqTWDsc!fo&t&TZW;OJLHdiNTw2|gHf*@rk6i#E7{a6g-j#`xW zsQ!4Bm+D4^jVpeO4_>vjDIRCsS2VZi8aXm1WR>rWO%M2hO#f><(4O`FUD-y@1Yy}sSCW6K=K}?LNmN5=tH*;_oKJnVM_p1f^x)gUeBhnFeq*w_5tu=JGlw8I z3!ZAdnx635w$^1Ir$`@2u6L)@oq(J`PvBVAtp`W6exJ|zz2@YgoS$#GIYI8mVV3&$ zlW8uDV?x!KXG7{=?Ml*kLjfC-U8=a6yLzeaw!f{TmtmJPVJ&&_=v6g8(k@#Wq2>a~ z2#XC-8@TK-`mj}d2r{$MFCRMVeL|RJ!M+lFBS7W5w#lvAMu1-w>OAjy&$DwKv?#M` z^=z?og_XL{4(6qK@qNzwIcx5Dln%9AnSW{JVXK(YVTK(!_@T|}r2Dd9m;FMbJwEQY z#f4jRO^*iiv@=d6y_|B@ym+GVpS9pdV;XiCuu@+r%N+2?I9^IZ!UtkgCA0<@KB7cO)53Ypj31deQzR(yYON0w|I z!O?I}F*>6Sw~iFz+Dugt+7~wFS$KwPj-9H#hBLb9?pNI7N9f*NxHPDFe(@;!7AxG| z9QFzqW8gZV=?D;RuqD*E7%1lF{^8h0j#}Cht2vQk)&6>CU7lCS#4%^jd@{1_>!{@| zp_+W%2DL|Sy9HH`4>>~Fou%16Y3qUb z^-2TNJYm_UJFF-A72DeeUjv#p0@ur<3oJ5{m)jcB&wX`uqrc%Oq1@gTtTMK0M^-0( z6&DBwwQqkM=%kleH>4gjI%#eFk8`qK4KFP{?N(!t%Xpsm_6C0OxksT(+^2AF#8ui4 zE-)|&EVGuEckHI`8)JQgp8dLIg3c^%`0H>eP+PK9Xy5cHAQ{SQT262&3Yfwz^v*Ec zJha1qh|oMZ6ZiUb=A0Xsc0@LaXD=xYHEdtI)cq)sc7Ji(cP%lyS+(;Yw!Az-U<^BY z-s|o9Z7PGnHaWKKgyvt`iNe)m>uf!y#6;Coa`p8?l7oMsK#hA^@>FYx`zNpA7z8$Q z=99{Zq!&Zmx7!PStmlNTA#Q*>LWhkGrP0=>H0|?Tb)R`bEFIVVpG~EN#G#WN{f$ec zA(WM7#wtR&*~->qPsc_CS1=Sv(fE+lzNV>V}U_n1<&x^jIz+P>j))=*OUwRMlmbt+Okde zJngLWKaC>l$yV}hJc9rEQ)@iaZ|E|L77%K-MpQH%EFAviT{zUl^Yp$+%d|KelmA_A zk-OZS)lg-;y_bM*S_fRxwzOw?*129N9p`8mMxc#vcffBq_pCb)y?-lz!76ImWlzH~ z4D}2C2DDb@Uz+y&m9gm!pKX>vhk@$wCpt?nhaTaS8ps*>)f>ul7%Kqb z&Y)8*3taTh89N*1ilx6SC&6WA`?B_z4^CZh*E$6zLN1;nC?akmwCIO-PwUU+CLg(X zuy*yR-Q&I?hHS3CdD2W3uD*H`r?!q*ffp&>oQK34=l?qGZt+umQh4H=`1@M?;e-k8 z>On;{!)|#UtMq`bc+_mGjTy7(JLMNmUhRZY9oavTiZUpe$PICHC{7(Kj(ek=X1{aobx%avCDm_)8vV> zCcJ>~bC=Fc=99C{+QyLP_BVDq$jK}8SlzS1xASY|oH2B9;F_2lvg%pe>cBty2b zCsNh6A1b#>jI{N5S(LZB_#NX1?!(f~oAhL|W~OCc$e<=WA06LUr&`(Z?tRkn`ZGyC zsdvoYVPlct(75){8AMR+h33oVoo&0%A3nWsL%e?7)4@guO8WX=PDlM((6C?wywb1k zcnkYYZZ7HO-m^0w-gt5MQo6KX(o7A1xAY)Gl#++g?Tvi>w(>~b(CN<19j~mb4n4aW z?X_Y>UtLq^1D!6fT3x-C6E=-mR}WB27ip{uVa|9R(=XrqWP|?&9ap|hjw)-}eP@3` zi=cLCs1M;KHlIc2R~`nCc{d1h?`Qj?O%uoW1-)#|y>EY|qRbRg8If@PCu(2X@n(7t zF*&t3D2FhslyIc~ZKhl7<}Ri>c2aQB%Jy#EUT|A=eH3E;Loan3f+*#E`@?scvqd$N zy(Xy*%A}E79PXKPI}zBCC{8}`&Wx1!>dNJXqIThAYVA!N0>;Nq0k4(znr*X(gj zb!&3%;fZQL^<@V6`LYEtO4&{!U8iSF&;{>mXB4co(bqWDHWg;sM(@}08MkBi+2$Yn znElUV?_N@yz2>#iHvM@{2LsagFr)O@yQy)U*d@&E)0Z!%9^@A~OzfhzI#Zt}E!k2v zu2S7iFUKq+A@JnMOHs3evWw%!zbDjfn1ni0Be7_bHEItrx}6z456UZ4J!c8~wH*z3 zt;_V+u*+i@@R%ful)9`ji@B^C-8!^4p*d@UpD=HaUSNF8o2f@llI10uJ7*r>BA>2i z6JQ*F;#e|1GRZfy(AHh9TJw{h_}q+Z5vj8qrtP4C$_4u)gMOadt?4Y~7tD zbI$p+Gv0*O)lYa`Ixc=kNkpRY4oZR3!9#0ZGYMqPMAtcny(MiyExEik$6*ox%}(7l z-vN2)^bRtz?+$8l0@_ZKE_~U>dPvdvownkbUop+`R<>@;Q}6Vk8DRZsJ&S_-zZw|( z!HKJ!EY9PqGfcJj3BxoEoaqA&WT{? zC-DOxtCXJPS}}iB@!EaS%RR@U?#$N7#IuG!KHgADhMTla9XJr7S*(7@uY+QyZqwBu zSTOJXgGzYSJTUPc&M=t7XU-?k`YP3PRY~SA08gj~$ zXFB<(lF!{<|64$Ira=+w@YX3!n8G@r)#V>zhDxm8quyM4GG{POUXfr0XBm}TMJ7yf z6kK?^bC1fxJ*{B}HxLfG9S6J4ZS<*o##!OWeMoqWTYTEKZtaQF`OJdNni##paqHDH0CPj!c4kSkZ(xDbJU(kF78@ot~`<~L1EsxKD1P?;;ybNyx$ zHpax?>emz&tUiiF*Cv(m`=jDgd)2aQHXXxstLYWUV3dtoiGCn)j)>2=H{nHJW7%`x zl(5)q6(^5m|I74upP01UXY2J*Ni6LfTb8NLZQ77MIjrm|b`FLpU%0d6-~V!qa`(Nv z?z#G9Rjq=#7^LBeN8zb4$I3M(7wODTV=@SEEd~V970Q_t2ID;|;eP*1WARg_FZVCL}NC7^J<|8mEJd5P~{Nzr+o@>XT=z}7a?+i6GTM!WTDEJL!8OSCAYJu8y0zX)GYcDaaq zPs4-QyL_%;+Ob!;Q)5=M#%*3RSZ=Bo%uf7}2QOSwHHg_Mkrk@cRWr|BuQ+KwFvRa=ChRIvvwQmC2aN;V zsb=hWYmA3(r+m|b+Lw#Z{+_dHyX@49`=xE(Mn)zr$C}}-ISm1EoonvVOgNo0J?G_Z zJ>QWXy0>1pM0y@+onb=xJMS!p><-+4V zt0;YqNA_7I=J)pB%9qSqpYc$uD0ax5e!1O#p<#n@S#KMa*L$XFJ3T1hAodj%<`~j< z^j7tu8G<7WVMtbI(3u0>=}*#vH)VkXlTWBzYOKjK8O#b?{Gd{gX_y;dwYgvGMtaD; z$S&=UW<<}brsBXyIi@`;SgqX~ub!O}el7OIDtd8ufYHJ_v&}6DX5^&6b<@jq^3r8F zoZ!2*h0({V1;wPkE9v{z+OSlX=niVt?@E~+vo|;o2Ae*O2h9LpELR#^B(MTFB0tbd zE)YXA0t`l9C>I0lAW(+z1O0hI2D0<~Wh8>fVIWr#Ss0es4h-NqhfBca;Y&T);X!OF z2f2_rkuIk}1OiY7AmjqRP)d_CkV;+}^tWOejYKFRvLFW1i{*~66G=b>!HQsoK{?2I zAvh#+B7!dAaA_X)jw2M%69X9_lZk0)bZBU(RVdy{B=JXMsZ=T&gG1wRC_I78!V}AQA|XP-3HXVEWeg+|k|RdQAt~EI4lRxtP&_N?r7{lM1$rPr z{y+dU4uhefFgO&BiXN*ENm;B>ZJ~4|icmb!azKp6T4B%v!6zD0nM24&dtcO$dP1WZ z+5?n|f+cLwAp{i4jK>-k^Mj>hZ3at0#gcO0d=3{4ZAxi*td5fl%Y9Tw5k`NWK&;eI zpvNLP>`|OJSi)CgIBYb?2L;eZq!2Uq6TD(%9M$;5ABE(zjfew8GLbYuB>u9_sQ5EQ z8ISuHb`+A&;E-Eiw(v(@ls+r-N3$2PgB8xX*fWsOiWP^)p^-UQ0+~v}pg3d<6-5OJ z0E$W>6Hx${;D^BxNC1vZ9Yf(Fl*#}h8~lTU2T`!8BoY_E<55^Hq)osP*(g5{#G@#9 zkPDEh1QL!&97EwI;X#!K@c&=CQRJCs>+Zrp;;b-Aa^;FUACPfH5&=}cJRwIED*Y(( z8-^(7dD;y@p<38#sh2EbFM-Rp@GfTvQ zh=+Hm$UhB=9+W{qQS6W-N#iscnT9<+rfV!>nn#07TbX)}GJ8;*hlRW^G=l%Q zmyEJVMO;}ZAOUUtp+n6;+A8j5g!><@6JckEfX*5jVK!3D=AZ5%GyqhT>R+D5;ard0 zl7Hcx6bJ$TkMhIe$S5wwk3i-^v4HN7 zf7azOP2zvxFOEwhQAiXvibTYMC;|ni^Y5%DEYL`hneW; zzrc;rSGG;j->Q#=4Qtzp#9`3g9w2iI6@JzH7l6YIt~@q$SANy@Sjcc##*Dv^%foBX zSPf0-=+QBKq{~5l=bwCybkBd%1OoBh$T!9Jd$_)b>zg9*P2lgR>wCDqDFWXF{(idt zYvG#s@ryoC2#xlk(ARjIc4)gmUjdHyTjFF7`=Izqy?8tpTA3hr_Lf5bQ>;_GRTh~g z%ArNL%!TCuZ&jV7W3786UwNx|&x{Jm2R)uo38iY4O+vxn z7as9nkv{&>9uNBT^IO$?BkA@o+eA?$+wS}C*2fm)6gtyT`mO(shlCPe8R@&qhbBGb>77e+IqxaGrN`>ylm>fa8 z;Admk9tl`L{=3TO>gOX2(}gGj(97PKj9G zqMxFOw$@2>~%-2!jX{CV6Rl?lJW_Fb{;UY#jvk+ySGl3;hQ7#5gx zb#H89TnR@V3JXu1-edo)-RWiV-$Jb}@)|5kOg1I;>wa;7R8~J~!$8h(BP~?slJjcAv@fR{Z;|I68q9v$%gb-EUr$++vhA$@GtXNv zY0O3k1dU%wWn?i~`l+~qHcJR2T|i14W-B`zf;1BxR>ClwWJCpI5oL)JU;k*oSVS4) z#F+{`s<+0I#Z*$cjZ80}mSHHLZBQG<6SQF(2hIjClMEqpm`xTt?uZk6e()oKKlB2p>L&VcP@7KU)Z z7W+tFkoGtUq}^bntPDk4M4q@r0bRnxiN&5o{#V<1nXUdr7JC~zmLlRHtOzDSk*-8W zgI{AUv6;MwW;7tAi8PZI#?I=nE_K#onxXB*bT=ve?rsyaHPP$+xw|}Gv$@OEc4qQi z7C{@*E|vC-GAoIsk#@SoW*{feWlv>fS7*;qg&oCtERx65?Xi;%svDWdLD97O|y_+|nz^t6#GENhRUW>+&TRb;SI85$TMU>X>J-8@EuA^v%Y zz=;7tj0U`rwwVb=OPPrx60ur}G)Tu_z)b&o!sBTZZDWs#)XFqSSHl4+?;69CEp~>m z7|7%VEju8gC?j5|R-=ScCWi|#l^Ry4cHMfrSUNf9@zHjNiSl+MD`B&fp1l?)Zr^PF_T}$R z9*uX;;)KD|$Fv5|Rv?WU)BlR>aDcu*!fD zu#p{>5hx**78JCX`Dc~E-;FR_f#EV~dqeu~m7!x58;S`_5oy#S?Pu0L@V`{KC+mR! z!UpnJF7P_?e^55xHhjDxw)gSQ4OHW~f56%1%QgbS+w?FE(rK(?!T9E9d77xH#5-S& zdR_?T`D~L0x~oxL9?wXq6?Orb%*VNj7u zIY?7h0>xf1?VihkjLqcLfQ~MO+1&{P9Bo2hsRHhty{*$X%HEf=e+dx(e}Yb3)qnB% zC4Y3B(JvVlh{Y!XfN+~UE^a=6m&XMF;Wl|(+ZYY19*8{ z01$4I$HmPD@bb6-AlxR8i<=MN<#7Q(xJ@1xHy^;u;{t$in>;RVK7g0U1pwhTd0gCl z056XV0K#qZxVZTMULF?!gxloA71r^TEoosNtu1Arp*=Fh2D8uKiVR6{k{Z2B`5@4&W9lUHxLv>ugUv!A_VoEl$iKEfYC%^mBH1ov18DAW2dRQjeyzs%by1UX#?r$IFZn>zTFI@a_Q=YgoWp(cH zy^Cl`)3`f{Tc=)_`qxFdL4&ts_GnsLTr{M`KBww@^a4}OThCr8{N}f=)cevZL9Mj+ z`TY>`UHalj&fq_W^ea=X5;hCU?Q?bFywC@sFNK^ucF-lDnY_lB8;PTZA@2+JxTokM z(XT4B=((I#p=G+KC-l%fwGNUwCzUCL>*iI@6aR3+b!D{M9pz?PUK-l_P-Ru_>vYKQ zpf{n9oD-b;M;_iT$P1cw`0b6(wIAlUsIlhD6~kvVelJ)!;9NlqlUjq3O$(xq>9!k1 zvqLPa9u-xV^l*RgeyQyJo}Wj3tdFjryL#s79TEFiGf|@z8|LKFG9b;_cgp$bJ|&BiAfEs>;37xYUPQYY4v-an#TWC0U%TUVl_!_sWK;kAB?$|J#cym_ zObefNmg&;6OHU>Adb&qx(uL)FE=8@FkyS^xRR$api8Bx{0HYiCrqq%k1 zB>8yPSvN-Cy5f3uE%iZW=w)GjB$JVneK)s7XDHU}>UqLdowhuT%;}pt3VQHV))4C4 z{(M8|8q7 zbsyXeCi*O>P(?3(C#X26QE)dQV`kFbp&@UUSAS9@B!1r~ai{64p1SSJ=BMmyfcs_F zzF%IQx9Z9$GAC_s%;p`mYiC`y>iRu(*%HTc+jldnaztku0Uwq|-# z5?jM_s;}qtdRkCDX$?O{U=9=5Km`p23L%g?$i z&LrM;56q9eA-%Em#zD#b&mE~r+jTWBginnax+8d|U~7?d_zKsDwz_cw+&RH@J?6~Z z{68qmLshL6cig9R%Ql4{Sh@11ZliMV>F9m3^^px@sdo#hjp4`lVwW!5b`M@1-T&m! n-ppsohpG$aYc|>*%Ag}}y|QIn%>xnJd7$LU(-L+~%3u5shr5e2 diff --git a/src/qt/res/icons/editcopy.png b/src/qt/res/icons/editcopy.png index 1809318b8637600d789820c2521c3e4f5312cf51..34ae0ad13c6ce2a94b71e609961971689d7735e9 100644 GIT binary patch literal 8417 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 C-NVBG literal 16340 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 KW6M+K)&Bzei!y2e diff --git a/src/qt/res/icons/editpaste.png b/src/qt/res/icons/editpaste.png index df3be8bda9d535080d0b6743d12d605fe6a9915f..10054f4bec08b73e20e394a2507fa75b4d6423ec 100644 GIT binary patch literal 10319 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 literal 16762 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 diff --git a/src/qt/res/icons/export.png b/src/qt/res/icons/export.png index ea16b407d5cd7fdde71b4dd79b1a9bb10118ec67..63d7ddd5f8bbcd745a21f7d5710cd20d5436109b 100644 GIT binary patch literal 11517 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 literal 17625 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 P=OZ&ceBBFXM122mKcwdk diff --git a/src/qt/res/icons/eye.png b/src/qt/res/icons/eye.png index c988a4fab464bfb889ed11ef454cfb63c32980ba..33a1a200ef7e53b5c70b1c2d65438d8a00100050 100644 GIT binary patch literal 10285 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 XlbJ`0V1=&z%1+EuU@< literal 18230 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

loxSdJz1N=)>VBL}xQs*vqzG7QJ% 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 RWAOJD;Ogk<}^&jZc%##2B diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png index e80e52da9a41ba425762ba5d6b5c85eb7794ad8f..06695db2a2c06bc7a9b237e625b109641d1cc4af 100644 GIT binary patch literal 11120 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 X?t!5#WPc)1n;=~+L(P2kQ=$I@ERNb} literal 18197 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 QfR*tgLZd=9k58Wa8&cRmRsaA1 literal 15664 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 P89+=8Ee$T~xkdgDB!6*5 literal 17398 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 diff --git a/src/qt/res/icons/notsynced.png b/src/qt/res/icons/notsynced.png index 1f3bd1727eed277f1d17065e18f6eb7d7803d2b7..417e0be176f937ae07e94e920ef780b00262ec53 100644 GIT binary patch literal 13268 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 H74&}qgke=n literal 17065 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 sD0kZ@2D`({;s5{u diff --git a/src/qt/res/icons/staking_on.png b/src/qt/res/icons/staking_on.png index 6326668caa9d02ba7cc390182d6dffd22de0bfeb..ab24eecf3c8bcc5609558db6ce2ae2d70257c1e4 100644 GIT binary patch literal 9668 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 NM1;-=sh*O!{NFJ<%#r{A diff --git a/src/qt/res/icons/synced.png b/src/qt/res/icons/synced.png index 9d780a0b26c7b7003255e8b5fdb00292742a81d8..651e6afdf0e6480f253a7b81ca766ce252a7b45c 100644 GIT binary patch literal 11336 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 Y=)M7)EBw$xW;p;%3@r4o>$-&f586mnQ~&?~ literal 17317 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 literal 17143 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 YG)q2QWtBJG@YfXn6N7wrc}Fk$H=q-($N&HU diff --git a/src/qt/res/icons/transaction2.png b/src/qt/res/icons/transaction2.png index aa5073a11b2d4d6f7fa1e9e485cd8143e9c07a8e..76d5632fe8e82c2e93da01ff2366f131e6a46513 100644 GIT binary patch literal 11336 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 c?zP5xP=CTSpBY+ADF=YArlCfe+WCNg@R5gP>s5 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 YvWE+gE8Ggh2xoWLrX;Cv<$ z$$p{YGUZn@nNacLDI&Y)Nt}g+hjALJA6h5Lz1pc6)yvPOgRX4fJm%*xr8Ow1`Q~&$ zZ|>Bvt^KCIWTCKp>og!J=is#W#DCKNv}s#^#?j|AdGF}-{mRnHMXrXDM;Rrl->o`7 z?I~_tk`=m)weJ_-I9k5*d?w@5(u;zg$>dSn}&t=1<*wF3bKc@EuEyI{BVW@^qM7#757_ z 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 s64bq}D!-(nwOLc!#;^&^XLNvVjyr#`Fkfe*{$~ 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 MLks*heb<=(2Z}x5F#rGn literal 17473 zcmeI4dt4LOw#RqELkJ*2K~${9_$Z4Rua-y?ARQ?Nijyn7$&XK+CX?hcZ}Jj$ zC@oa&2gS=p>om}!bqgY->k_0q8F{XN;HBro0Thr!@@u+kbg+}Moczhb2 z)b}C_2=F&AjVzWQ?mw?@IN0(g$Ln-zK9!oBoa~;=bXRHOsB|8WN2M{S37q?KyqYMorAB$?t$VpK^wZ!+05(7>zjx)kbxft1=lb}&V%UZSSb z-D%X}L^A1sMxCTd>^U`=lnNz63P`Eb!aDk}I(58Cr_#o&Mi_FyJ>tM{PC`Qm#vb;3 z6^dbp*6IS*!U+114y)8gq^KckIHXl2X{1oVTKH0?4R`fAdF)_v-il=MjCk&lUOs}% zRLWDI!y$Rs++pNcZH?~ph$DL+=FQAl(Gxk3^LQPs*gFX~|9ke&mxitndNRB7PT zf&@%2>Tu0NR6R3|AEeakBuXh1Ui$rq$9HS_X%XWw0SejFd;=u%v8?2ZJS{aAP@a3fvYe z<{a+nom@w}QC6a65`I$0g-omrDr&YRr7>;&?#Ixi%F5Nxh#s5E0NJyGDyN(LMFEw-vrchkqSV2Yw#BQ(6ahpuh9W z;3fT?Q4z7QK@dRDO$--0AA}dfg#dzXVz|)xAiNkZ1Q2u+!-dWV;l*$vfS{WgE_6N! zFNO;N1l`1Nq4Pm_Foe#o`;X(jGH!)o3d=Op?7Xk>niQz)$gYaUw5J1pP z3>P{dgcrkw0D^8}xX}3^ycjM75Ofp6h0X`z#c&~jpqm&jbUp|#h6@1%-NbOA^Feqq zTnHfOCWZ^055kM#LI6QGFzw@M5?SK+sJL7djt=7sG`Bf^K5C z(D@*|7%l`5bQ8mc&IjSea3O%8o2a-5gAd$7O86<;WcYE~@LL8S_)%PvR1_Wxz`7am zBfXmd=z0Sme+D3l2Ec=80Qh?Va8~`-sx$Kdu$mg=?-QZF{;(h=(P^>cmeb)vqK}ox z)z!6uOg!gyaDG(jR(d#lq1gWupFELx6aH*wjIY1gksae!?PBX5$(ez7FO6vZr&++l zC~>?~a9L)<2m3bU2fGGK9;GrLH#K^nmOVXrGxr4ZWookb%lv#9@#5R^KC zoPU(1{(H*P;B(i_F8l4OR~WAv)7q9(j(nHn>fY%L3a!;CR{N94o#Q)qj60PVD)f%_ zqD5sj{VFhy6=shsI0Y)ruP0nQ;Z5lHBA}fE@~S#+T0}c{7MNTi_!qFt+UOg7WL(~c zGMCQhZ(iJ)I4TZ*8y73z8DL|O8_m}@J>uZ(XM^jb#8#DKONkw>!l})YLf=B*YECzc zuJLW-fTP4|b{WPyGo#0dONiArLbm$7idlGKrMWxqBV4!PQzx*Y(y5wTN6aTQg4bX- zUIk_wG|`*!ZQGA+cH9`XsAF2T+1YM_Fl}nJOUF-lYJYVy=zVF|{PtQJA%f6rYR4lj z-+~lFWWC%|o`EO6xi8F-07txqaH{yNLna=i&be^Ah*)QDnDV6drLyP>e3GPvQ5DXu zTa(C(%@V43nQ>F1w{6iLn6cI7TvZs+4~#iu5p4J)`|{cEXC^HdW{~{LlC<$(R7bD= zFsKz@msa+Evy})ub`frz^j?~6egWCs)k*-ON!LX8yPtO9e8%Xf8@{d-F&R!2P1yUZ!LEEoUzNDaS`MTbLOYpI~?cid|>{O^~Q)l%$WwS z{ZBPp(+_U1e?~DZH@vj9{nGfg{&=Vuq!|jGIuC|*jUSbtd-sH0I=Kz1bL$Fd(^-(1 zMBTGl_U&EQwp82wj(d{S5`t?8(e5bcccs->8Y5*_lD2iNz**7Fop39TPoP=khCe<8 zHal;8j$3t_(rK;!6i-}WRf117s|_@3OS9VsLQ(I>#I`6RI?s{Xa8I= zBeean%MlUukElAU11omn;y10Ps<#}xqzH6qG6WXc8s>F-700Ff2y^bGcz~KBf-!E{ zqb+i4wZ+=h*_uvX%>0=+*KhMqoCtn(j%Ceps|!r#WTh{htDNd~xRe}w6oTBp8bp=08 z%vzR`IR&&_OrA1v2GPD`CEJP{gvwfz{ z`6NSaX?QiczScXa>5$M7r!KSX*!uEJ(W7k8Og>%w)xO!_+U683!%}<`SFtAes@q-Y zrz*vv5J%^SS__b;xSo;?#CO8&D(bhrbTYK8J`-tccK$uM{@mR&Kf%BP9U{xMS1qTz z?Dr=KDdz%WZHh|C7KLlSt`wyv`Qs{Z$vFw2vHr%&4~Z_X<~gL+3iP+*!4-^*aWM@XJh2cE?O4mrC;3LzU}CELj5>EbS^)= zyjYcKuChAM_u0^9abCNdv`{1lZL1zi&8mFxLAnc?TQ=$T6*t;)S+_rQH2CecPE(~U z2y6?+YijQM6opW4aiZ(;^!v@VmWJ+zTd&M^x3k%|jSD9dzh@#$}lzYWeHp{bF%wF@{zGB>(A8G|(bgi;-1RE^Z7jZo^e?Rl=Vequwk7t!w zo)>`!)u~pk^0JE`J2d>FjOH>fCzBR=Bz+qYGUo88@$>cHoqR)x+I5!p0j{&KRX9ra z<9e0oX+%c#$G?W`JzGF9cq}GAd2^EV+k=12xhFj?|HYFOeErnX=e|+T$Gl+1tiR!$ zTl%kEWe$0pvrE1{bnZn~Y1WNpo4&Hzmyt-GAh?Cz}Pjxdgj4Mb@@BzAmp2RO8i^$IK4xF*EaD`AJb#SK`)?mWUSaxu*8) zQm@1XjNBG-a^wTI4{+jHz|BJVWzT+$FAN6}1jGEkMkiJGT#x~bKcCEKzhe56kD!1B K{^h>W8~+>7yfL!? diff --git a/src/qt/res/icons/tx_input.png b/src/qt/res/icons/tx_input.png index 4a480ae61d729757ec1e63a4b52e369dc802c624..934e5621702787c89d31dab5305e0191c9d80e64 100644 GIT binary patch literal 9647 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 literal 17523 zcmeI4c~lc;_s1uJhykPmf+8*ApYB4DdlX-TaMxPa99A{1q*OSLLUe~MO=cf#%nbK3Lv_s8#dCg+gk-uv9|GxNF6 zb7%6$@JZNw|8b_1O#uKH7Z~6h0e$KWe`Ci$?>`DeSD+8PDj-$^0A|*PKMYV%I0*ne z3uI9-+L+J~u2?B|7fF-}pnJMp1&sy(-kfxmNW22n5)!~fnSxJjKU+y8$RvE?hs;n) zsLBUiCJV?^gOQo@qr{mj#2g86j=+?c&V>ZzpjJdkmnSJS+;l#%SC=>Fd-o(G>qV*RD%SjJBuWy(%A$LjysjfVbd712{a0oMW%4bR0fGcz@v?_{3#et%^$~r=_L2r_tS&>O?Y?!{LxAG%}4wf<}-u849f^ zoutq>_K6JW_<|a-TBg#|~$nd(j< zkCY@459X*+)JeUECJ~dtBv1}2v>GUnI%1w`nNq9NEK`m$;_=Gm zBTlW+&P#<5^dlWHQxlb;0?84eMwy}(gY#0MQ*j*W?6orKP;uT-GDJo_b}(HwN}3_k zm)5%!`YObO&Xwz<21Qz>I!dWb67;RIumOYwA0NZ2@*uc;C{sw3X_{F)GCXCd-a~4j zuSg3D44KeMBvBbrR1TL;=Q1cH3Y$xz3=`=a3DXEwN@UWE0S%5pgT{=4QVkl+;Tpq6 z!Zo1%BN1sue@SKd*kL*nF;}Wo%SBp&OfE_U$tp!6k38fYHga%Paeb6YN;Py?pn%RJ zkK`Vf)w|NTfeMXQq!5FFz5>YME|W>PG!}!I05T*bY62TNcN&915>X^{5}TDEqEW4OCV_xCxIhnilrnb6Qq$SAcIO`GrChVGvv`(G%8 zMwI&Bm4PivV6Z6^4z!Qx9FkNDH4l+U43b223Pr+VCQzyLgn=^utunAl22n;7jmBlt zxfB+O;?djJ{;@K=({lex8HQG|c$r9%2ucLxfioL${9mfvU+aKQH91LZ%ha`e%c=hh-V=cKR;GkD~2=CDYAW?!*}-9-2H&pt17iw^xdAP@dLc(1h%UV;9}FGHvF zPpZPS&`DrGkWCa9G9OqJ#RUU`Y@)c3`M{zmE*KDG6UBwh2Np$f!GIu}C@y3^uqcWP z1_aqeaUt`8MNwQZAjl?)3z-irisFI+K{iob$b4W?6c-E#vWenC<^zkOxL`n#O%xY0 zA6OK{1p|U?qPURxz@jKF7!YI=#f8iV7DaKvfFPSFE@VEiD2fXP1ldG!A@hMnQCu(} z$R>&lnGYzzZ+YwC=?zS$-X_m$LLIa>7CJ3Q0c+0K=4#i+-mUxcSEkmq*A#Lz-?vMGzO)L;YzSSD zZF-;x2wHSxR+s2x*ioFjkssDbSDXD|MV2CdJuTDLO@HM`p@FCnx@C(ktVd)-PqkE&>z&_x&7EP*g4<;&@i`bqUucT zn?#JO_qh^aJ#aQ|ijQ+Z9$=sSWY?u|d=62!yY?Hv&1ecVJZz?l+i@yrTLcE0pQ#e- z#V^(vztJs{*L0Ks>93kr=LKIkJB^Dm>&7RI`QBt&*R!$3+L^lTLU)yqxpNWbj>$A& zot+(E;p<1L2iD8}Sm*);mzX=BwquuFeel}IEPFF6c`f#Q)an)g%H`lEeHJ=pH89ob zv|x;tIo6^h_QfQ5+csm070=2DZ&4BvYooWs)1qCAu`xlay*|Gh2jyWW;U`D0o?v#s zst9<(_%myEB;Lvu&}Z!=+{P9eyXr0QCE@s=+yFgx$aARJ_@NEp^u3T97J>h1me*P1 z`Xb2Vb=;VGXvVqr%%eWd1ZyuWar|c=T-O<2O2QWCqz9sL8$LDOR2+8vBYjBAj05dG z0yj+MB)bA#ir!xDZ@h=Qe>tYnxoQ%Ab(6)pefM`_c424czRFs90?fu&Wo;no`YZ z7ZEdMYUi{0xP_Qnj8C-gY5szaK<8v?)Z++ z8ggqs&5hKpCw1A+?KqlLXV!90#y(^5nG=o+nD*(#C#(Zl z-z$5(_SBaDdSY!G0Sb4U&hCmmxvtZ$E*kL9xc2#DZ`lNbQHYVii>UR;?^)nz_wB0Y zG8fM;8h0M~q@ntue|>hr%={--5^Un8AF)~XGcj$cxV*quUe~Nc>~_Dhe(8hzEo8c6 zQEFO~xo-MKR` zNz$J!k{1J&SdYVjI%&5_?CIHFez@NX7CPDQp8jZxt&o!A;e{(|VW}oO-D=wS#TVh2 z%i7N`a$WTtSA9uYK8slwj;T4}a#kS6R*1q=b3WeEtn10U+^k#h(+s`;%jr&b^Y2mr z3>P~-*|S7&iZ91@Z}}qr`IUGJ=3B4FSb?p7_z`xENohWXimPt^9eb)}m2v6X7LG~b z#1>L_Vrvc1<$3*OO2Es)rFZ`5{Pvj4Mrf8Aekl=q`21pBgC5w_dE76$>~sx2>w0-N z{d^a$?t(sQQ>XoQ^SeiETjE>zn>wE#x-sEYVZ}k+;n`jJ_wH#{eHjnvekr}8XO2my z`8{v04Up}4E*{sR&E2{A1h5}d8~2oMS6z83&U|uDik|g-y9IgwibzZ<&FFPXhJsaD z!O!d{ue5s2$h-n|$H1R=ZaE9smu@<|;=y7ky8q8+ti_wnn;YMD1_uP$Md@mqw#G-v zJsq!-pDq7tdQX@MZ>!U4i=2nQyOa0Fm0-1@X0&zFoXD+r?wfWx->jDL#s_wHe{=8P z5`Wu_S51ZcxZjqXAM53o%1>5@MFRU zPRW0iy4F`VFy3xt7lwTJhtXAB4VLA(usynJ!@Z5CqpI#1TLxcy)9vQ}=xkM!nsxC= zL`mYSqg6Y$}U!pCq2PVq^1nT)%($ldl{avcwn1Ngb8HHP(0AFKumpYoGH!$yD0PwBq8K zE)TKVyPlGroqodcIcuH~QcElvlZ)r&&>3lE$NZPPQY<(ZcqILYu@~fw$RfkVdE?)I dyV30lXiY1stg0SuHvC(Vz5xQ<^dd+VK`f-4Km?KyLbre@2sn(00@4&6MWm?+ zNRvJ)9S5YVC@LyomoDE4ILgd*X71eQyZ6_SC*|z*u6OOV_F8N2a~@*sw^@j+lv@db zKt!x8O&!7SaPC`30Q{^sAT>iEt51YFyK)>!K~NT(Nu&D!P)-O7fC9mE8UzyDKYqrY zJ=i2}x)3J4$GG}RZWv+y_?tDA`_J+smCYR4mOX}nyMC~2@d!WYOap)j#=@(!x91}d z<(z(b-3y*C)m}Zwj?2*Pez-6}c{4pTKiu_kI{N*@c-)B*Dpv4+oY z|M)zk%`<&w^@sg$<&b?X3A*h8A7wW+&h8I3sQ5J4^FDf9&(NxH;{)x_a|F#=*Sfn> zy9d>k+h3E5ewxjGpE#x9cr^~+FFTvzG-VJtF+QICsH$pKYV*Uh?_b=u$M4Nt)s!ux z|2%TPVuhx$;tr_?o}Y)~?#+EtTsUxSh>)9E^m^#yu4B%A?U(krmp$+shMsy+p8v-2 z;E~DDD!Ia@wQ5Ft&k=%c*X=xJI(tOkWpwz+0R_(#E!1s=)0E?h#|Fw$u_gGz4$rWo zlDOgRDu&xaH|p|;vZ85JJJfAbm1$VbY zjvOmH+F0{Se!sAlvG5*Bm)J4NinDD^lqSFMEn+d6H~DnbrE79JpFP_k(o^j4_<$Up zN61P=z2im~kEUmYVXCJ5%ah8R#nsO{UbI5wjKD5R!7n-NPNYf0uk0+Q7v?- zF6npo5f)B#NiBDA_pZXwJxAMyGBiUK{eDV_K91&eb(){;@O-9TWRnq4(zjz5J>he% zRzPk+$;_Jd8sn8fa(=}`$!vtTTE_m7Qx~!`183In6TM=1eyzdAN$;+@$kdHVg|9v+ z;I`%7iV{*)Bd0{Tw(vA`i-mV|BH!aile!^d1=nx;lvqS&RfyVLmT`tuc*5#1vS~pT=IAS{5FR#5*)c^ec!fYfyemde8)jQh>9WLuF^$s3#I&^bm_A9b>KzGyafzubq ztDLs~khbu`xj1VkK|bL4+UC>?4t?<=MYpXlKOu&_2<*8T)_Q|7w&T`~Zs$0Wt5xV` zD|%u^i&D0z`oZ?B&V5daov#wc*QsBB9=dmwp`68*$&ZU?-RV7{a)(9>OKkMHA7n9E zggEGTDnI75%?nEt*=T|}OY?`SooDz~SZ0r(Tssg`u2N!N#vFD|IH=K&?u#6fWCK%oI`?=UecGrogtMwW?RDl&7UQ}&o8_GN8$+`4ft*TDD zU9Uo0oOu&o06|x_!X@4t69*dB6dEMiI=07Fr8^{T=jAkAuI(|C@D6M+gw(0$v^nqV)RC%hj%v6J9_e~9|*lQG* z@msgLg|&JHdX3mkP(0T7ZjwHwm{}Hwpd=Gvk-C+=FjXK=TXh;qt^e3Ib3TRREi0W^ z&1c4QFy>`uzWi&N+-~DE4NII)+u-5KSr1i#>3c+=Hj)F5Z9_}P(^sw^?7 z3h$$w;9b9v-pWah7QbvbK4DgVyu0L+v3xBQ*H`9fakuXvam_~Ol8)-Rdi z7PJkxJV5&){wHg^A49KbOJvm4mdZ=PZ`HMmZ;Nav%5HbBoFiBv@jR2#=kIMj+Lt!a z?XfFSA34W=Oem5Vo}q2SY5A=y-U7v#Q)BdnyN}nOVuXTRel@O1Rh+uV!D*_g>k;7O?^ zG5T|)3tc#rTR5tjk(GpnN%NM9bZN)eYH8BXj5n+nj4F29q}0$5LsM84sVj*-{B*Zu zX4q70NM%o{7+ynZWPO4;OJ;jX^v8rPODcX z?CC9igm{;fkkgAvwduH#G}3FW#>lgp&l#4$>`venetXBFylJ@lqJpXm>AYR=sf z)(@5P`XphaNfMUBy2AVtIwur`sqSsqt7!r*KdR0o3#5h(!?F^4i=wsw zTXeNCfj^j6*~Z8TH;W1#f8p8&LC*}B^=#W4QQqy9Ds8@}lj>(bnTl3uL>v#e43!cd zk$ZZn6B?D*XSBo4aVlRrwd0!dK66SP1L=WLRz{|^cB$I!+=#w7hTm65-eRGhy6J}j zrKd5ni3vwJu^ZBiFp~6^fNfhJY-*apxHpLU8jY-V;f<-i-Aea$x;P^-MpF-;sd3P6 zG$^_el6C~QSEcGzP+e)(3C|*WxoOEGp3ye1aWNP9(Zk_WSA9=ke;@J+Sl6q2FT8)M zF)&sA^TgU;4mTi5lcbNCd&+glh|tXKFZG4hMFgHqxjC$O$8Xn$GIP^m2~>y8uyq{i zbbr*8Zdr7eVaa^R_1GCh0nOO^TQ|JeYUr{-Q}0pWv}WCa-D7vbR-5ewuAJBxRI83y zSNk!o;f+4j(@G8@t_rc?#d>g&JmorRp8WQ_HSb%kG_L@{wHnx)zhp|N9z(5?f2dHt zv!hog`L5Gyz0QRbrW2FtZ zk_xmMt>C=9rfcs$KiAklPn$_rYsk7-#^dpc-jU=rk!&Mdoc-eVC*upsxw0A76)j$t zJc$N*u12U9UJdmwsb0?W(;@&_#tpuKa(NUzeD+Aq-pnhT-?KUV0hL;=ra9Foobx7z z*V!Kr?mXdGw6aaM-S)A)g8V(knWAALD$?S%GfxFo99YPElAbI6;Zh@i?9l1-gxt77 z9!XN9gW0)M5gN=`P9SXc;jH^^r5^JLr(#1DGnpGyuY(QY?Ts~W@efqvM4lqu(sXs` z`vnu;P>yLu(Xzc1Y>8S?N3bWJH;7q38S#tn6dB}W%pc_`kvu~$9QY+2A*Azh=hVw` zh1LrdA3OKeij;ZR1nE!KMMMxf&aQeJ)4YzF1Y2ciq>Q>&D8(~#p-puphjcr$dz3R( zze<}SQth2+uwkgwAa+QvET$;^Y4aq6VtsXk3LZN4M&TW%dp6!~eB`{si&92?sMAeh zuTRj}sL0B!v%EHXJ-4(J;HL|JJ`XFL%Xl{GHI5t@$Seukm2**VQ&^;;<`%!BLm!g5 zmBU>+P5ZBB2&f$v&vA$4$RDAuIf~}5&t>hsy=8c{*E#u}c^K@JQ>?zDK|Wfob%(>b zr;j_NPmKz(PWF9DczmsVU8ymptEg3M{+eJab=#=g+Ws;Z)LYRVR!wguJdQ(DqS>=f zb>#~UuHJS@`ETakYE$g3qUHkxJZA;ZJa(weO%CSF`rqG6EVoFWFn>=)t0|>C8T>KQ(sWmASxei1ZEc7Yrmr@M$|M8Y!M-f;-UR~D zGYn>tDBb`EN(MaX41L(^ifR~?PSuC)z}X^gStfuN-7=I7IE8L=ri6M^2vnG%!AiYg zB1qs1a7fT#Umu1)F<2kA$V&u&bB7Ty=puyUtq*gxwTGH8*#H!)jnziN&4THHXqdrD zs2-b2BRZOzf1v=c^kH5c4vUCD1O)|Y2Vu0CY)=G=Kp-HHXapJ!2N7`p5C(@73}^T& zaVeHKOaXrio6h3UnG7hGlSF0)aP(m?P!9b<4oWFz!QkK*1KjIHdVdZTVFg}bL4QC1 z0*yrC;Yc(bO+YNy2c@>QU$q(jU!n-c6A?^eAyC>#gs<;!H2gVcf#2+XSHs^KyhTJf z0{+YZHU%&X1Q;BpsVOX+JDvIhS8Jm%Uaan zqL(A7l&?5e0NZB~L!}@9AHWx!h(E}T`VF3YEBjUBH~w%X|1uGl7n8&E_hPcXuk%&> zFNz#G?GNm5CI12k-TJP=f(9SnldQ?T<5Gze@#~^lR~EwzfOjTqmuDR9V!~G zgU1r!C={RzC+O$^aDpxlr9&m5sTcscjL?eV&ml1=0GALnp-l(LFeEYtr;De-bqPoc z980F^!0|{b6^_-#kq8t#292cYE~Btx)4{qU`7ECsmx>Bfp>#=j5&=twlK}z%M`E!^ zI37bLz$q9K3PT`JsaOhOk&3(OL?e4EeHdDMX?}|%_C6#Ijmh=}iAL`If3T>ytSF?m&Z0JzLNo^{Nnmc%eMz1Gg2nJ$ z6mYYEXu|YivYo(=0_ekZa5xO^o5-FX4EVU3f_528q$o80cT%_SNWZPkBDXD*3Q}Vh z6}kC91mg#;D2ZGApex_Txn<=Oz#ZPspo5b|e-pWWlj*~B!HP#B5h(8GH;CJxLcsMQ zny>*92QUTSAU6`F3rFh0Q5a`5iikuK!DfZj1%E6Oenm6c&P=9{K8(9IP;N-SifzG` zNhNVeU+D;NBnpnkIV15z42Fn7!NDKP=)fq@X(4}w<~B&E-j~)#v|&;fqqH<}>Y{L| ze;SiK5ldLapMn2{$;pcu#Q67kzCpjT7_m7)Ot!Zj+m5^spm6@2=X>CECGx|8^CBW$|ayI6)*fVB`s=wm!^=yJJJ`e{HBx6B8(yaX9d))>2ig|8@>RUI4db z|1c+)*80od`3KJVlLCR?xkm9KF+2hAVDM#E_%oL&I2x4%=uqG^9TE*r#bR~gcmfRr z$DjZzfCd|*4u<^ON&gpI#(@3vOBwzTT*m2OXm}jA?PEc|QDiJ0PA2G(;Ak`jKw|L( z0uo304_wy$%T@k^R`I`ZnTo>U&=f43K-NLSu}BmNPDYX_a0-$BC?XaG`{JG+f_vcmwP5wQN21@Av>x}!M6}{=RZamcmJc0Z z|F+bZnDh{TfLo@&*g2VhslFVxq;0}vg@D_<7soD$@u%j$16*RTp;N$Z^G|Irhb)C< z*|`{Wd1(whZ-d8o#MkrtmqrJ+p8w|Gmj?RZGy#SFW8`ne_n&b66Ry7%fxiX*C%gU$ z*WZf3-va-WUH@<4TKVk>Aiw}m_d($Ey|HI^PJ+({1;|@1Od$*0*SV_fL~ulyW$ES* zfvl3`zIh<2=`!G;AjitqOmKv6l@yP9f@&TW0^x16GBt7r|LbAsnqRuT)D{O1=g5B6 z)dY9@>-u;<+ihL-s{3jacuTWXS<0e&>K`6m(K7pbFs0M7eA4hyq>JyvNs)K=rlo}- zyx|Zi?nky{)(RC@O_3Ob6bY6KAKY1MyS+Por0RY&uk+^)B+EK+?#= zShDr!*=GN=?FUm2grA&KNi>BBy3H3R`&XE@bX{pzHT=LIT$Mg>@~S#r^8NBkpq7^Yb?XywgJ-XB*sYgfk(Y3tXlz(vhnA-u&Cg`0`XVDg3){bXO7t%anH{A!rj}?W7^}V}5&i+aCiHyOj-dBflAI;8LK_TKoTljhL zmi$iS3#QQU5pf}pCqiR<%0Jfldb|^gH;|pHKPD&}w#!!&PvUo%*9>oh;U9kthXlqx vy1XuOSW%#s|KG?RvGBbS-_J06^=h8pP5gn+_{Pk^9EVt$Z8I$}_Bi~1AN4RC literal 16956 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 diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore index efb277d3..55d325ae 100644 --- a/src/secp256k1/.gitignore +++ b/src/secp256k1/.gitignore @@ -1,11 +1,13 @@ bench_inv bench_ecdh +bench_ecmult bench_sign bench_verify bench_schnorr_verify bench_recover bench_internal tests +exhaustive_tests gen_context *.exe *.so diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml index 2c5c63ad..c4154e9a 100644 --- a/src/secp256k1/.travis.yml +++ b/src/secp256k1/.travis.yml @@ -11,7 +11,7 @@ cache: - src/java/guava/ env: global: - - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=no RECOVERY=no EXPERIMENTAL=no + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar matrix: - SCALAR=32bit RECOVERY=yes @@ -22,15 +22,14 @@ env: - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - FIELD=64bit ASM=x86_64 - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - - FIELD=32bit SCHNORR=yes EXPERIMENTAL=yes - FIELD=32bit ENDOMORPHISM=yes - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes EXPERIMENTAL=yes + - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes - BIGNUM=no STATICPRECOMPUTATION=no - BUILD=distcheck - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - EXTRAFLAGS=CFLAGS=-O0 - - BUILD=check-java ECDH=yes SCHNORR=yes EXPERIMENTAL=yes + - BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes matrix: fast_finish: true include: @@ -66,5 +65,5 @@ before_script: ./autogen.sh script: - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD os: linux diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index 3d130bdc..01fd0cd6 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -12,9 +12,11 @@ noinst_HEADERS = noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h noinst_HEADERS += src/scalar_8x32.h +noinst_HEADERS += src/scalar_low.h noinst_HEADERS += src/scalar_impl.h noinst_HEADERS += src/scalar_4x64_impl.h noinst_HEADERS += src/scalar_8x32_impl.h +noinst_HEADERS += src/scalar_low_impl.h noinst_HEADERS += src/group.h noinst_HEADERS += src/group_impl.h noinst_HEADERS += src/num_gmp.h @@ -40,6 +42,8 @@ noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/util.h +noinst_HEADERS += src/scratch.h +noinst_HEADERS += src/scratch_impl.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h noinst_HEADERS += src/hash.h @@ -77,7 +81,7 @@ libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) noinst_PROGRAMS = if USE_BENCHMARK -noinst_PROGRAMS += bench_verify bench_sign bench_internal +noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult bench_verify_SOURCES = src/bench_verify.c bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_sign_SOURCES = src/bench_sign.c @@ -85,15 +89,34 @@ bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) +bench_ecmult_SOURCES = src/bench_ecmult.c +bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_ecmult_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) endif +TESTS = if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +if !ENABLE_COVERAGE +tests_CPPFLAGS += -DVERIFY +endif tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static -TESTS = tests +TESTS += tests +endif + +if USE_EXHAUSTIVE_TESTS +noinst_PROGRAMS += exhaustive_tests +exhaustive_tests_SOURCES = src/tests_exhaustive.c +exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +if !ENABLE_COVERAGE +exhaustive_tests_CPPFLAGS += -DVERIFY +endif +exhaustive_tests_LDADD = $(SECP_LIBS) +exhaustive_tests_LDFLAGS = -static +TESTS += exhaustive_tests endif JAVAROOT=src/java @@ -141,6 +164,7 @@ $(gen_context_BIN): $(gen_context_OBJECTS) $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h $(bench_internal_OBJECTS): src/ecmult_static_context.h +$(bench_ecmult_OBJECTS): src/ecmult_static_context.h src/ecmult_static_context.h: $(gen_context_BIN) ./$(gen_context_BIN) @@ -154,10 +178,6 @@ if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include endif -if ENABLE_MODULE_SCHNORR -include src/modules/schnorr/Makefile.am.include -endif - if ENABLE_MODULE_RECOVERY include src/modules/recovery/Makefile.am.include endif diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md index c8b65172..9fb25168 100644 --- a/src/secp256k1/README.md +++ b/src/secp256k1/README.md @@ -55,13 +55,7 @@ Build steps libsecp256k1 is built using autotools: $ ./autogen.sh - $ ./configure + $ ./configure --enable-module-recovery $ make $ ./tests $ sudo make install # optional - -$ ./autogen.sh -$ ./configure --enable-module-ecdh --enable-module-schnorr --enable-module-recovery -$ make -$ ./tests -$ sudo make install \ No newline at end of file diff --git a/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 b/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 index 1fc36276..cdc78d87 100644 --- a/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 +++ b/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# https://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html # =========================================================================== # # SYNOPSIS @@ -44,7 +44,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 10 +#serial 14 AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) AC_DEFUN([AX_JNI_INCLUDE_DIR],[ @@ -66,9 +66,17 @@ else fi case "$host_os" in - darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - _JINC="$_JTOPDIR/Headers";; - *) _JINC="$_JTOPDIR/include";; + darwin*) # Apple Java headers are inside the Xcode bundle. + macos_version=$(sw_vers -productVersion | sed -n -e 's/^@<:@0-9@:>@*.\(@<:@0-9@:>@*\).@<:@0-9@:>@*/\1/p') + if @<:@ "$macos_version" -gt "7" @:>@; then + _JTOPDIR="$(xcrun --show-sdk-path)/System/Library/Frameworks/JavaVM.framework" + _JINC="$_JTOPDIR/Headers" + else + _JTOPDIR="/System/Library/Frameworks/JavaVM.framework" + _JINC="$_JTOPDIR/Headers" + fi + ;; + *) _JINC="$_JTOPDIR/include";; esac _AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) _AS_ECHO_LOG([_JINC=$_JINC]) @@ -76,30 +84,27 @@ _AS_ECHO_LOG([_JINC=$_JINC]) # On Mac OS X 10.6.4, jni.h is a symlink: # /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h # -> ../../CurrentJDK/Headers/jni.h. - AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, [ -if test -f "$_JINC/jni.h"; then - ac_cv_jni_header_path="$_JINC" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" -else - _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - if test -f "$_JTOPDIR/include/jni.h"; then - ac_cv_jni_header_path="$_JTOPDIR/include" + if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" else - ac_cv_jni_header_path=none + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + ac_cv_jni_header_path=none + fi fi -fi ]) - - # get the likely subdirectories for system specific java includes case "$host_os" in bsdi*) _JNI_INC_SUBDIRS="bsdos";; -darwin*) _JNI_INC_SUBDIRS="darwin";; freebsd*) _JNI_INC_SUBDIRS="freebsd";; +darwin*) _JNI_INC_SUBDIRS="darwin";; linux*) _JNI_INC_SUBDIRS="linux genunix";; osf*) _JNI_INC_SUBDIRS="alpha";; solaris*) _JNI_INC_SUBDIRS="solaris";; @@ -112,9 +117,9 @@ if test "x$ac_cv_jni_header_path" != "xnone"; then # add any subdirectories that are present for JINCSUBDIR in $_JNI_INC_SUBDIRS do - if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" - fi + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi done fi ]) diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 index b74acb8c..3b3975cb 100644 --- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 +++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 @@ -48,7 +48,6 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then EC_KEY_free(eckey); ECDSA_SIG *sig_openssl; sig_openssl = ECDSA_SIG_new(); - (void)sig_openssl->r; ECDSA_SIG_free(sig_openssl); ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) AC_MSG_RESULT([$has_openssl_ec]) diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac index 67a9d460..68c45a56 100644 --- a/src/secp256k1/configure.ac +++ b/src/secp256k1/configure.ac @@ -20,7 +20,7 @@ AC_PATH_TOOL(STRIP, strip) AX_PROG_CC_FOR_BUILD if test "x$CFLAGS" = "x"; then - CFLAGS="-O3 -g" + CFLAGS="-g" fi AM_PROG_CC_C_O @@ -85,9 +85,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], ]) AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), + AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]), [use_benchmark=$enableval], - [use_benchmark=no]) + [use_benchmark=yes]) + +AC_ARG_ENABLE(coverage, + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), + [enable_coverage=$enableval], + [enable_coverage=no]) AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), @@ -104,6 +109,11 @@ AC_ARG_ENABLE(experimental, [use_experimental=$enableval], [use_experimental=no]) +AC_ARG_ENABLE(exhaustive_tests, + AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), + [use_exhaustive_tests=$enableval], + [use_exhaustive_tests=yes]) + AC_ARG_ENABLE(endomorphism, AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), [use_endomorphism=$enableval], @@ -119,20 +129,15 @@ AC_ARG_ENABLE(module_ecdh, [enable_module_ecdh=$enableval], [enable_module_ecdh=no]) -AC_ARG_ENABLE(module_schnorr, - AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (experimental)]), - [enable_module_schnorr=$enableval], - [enable_module_schnorr=no]) - AC_ARG_ENABLE(module_recovery, AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), [enable_module_recovery=$enableval], [enable_module_recovery=no]) AC_ARG_ENABLE(jni, - AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), + AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is no)]), [use_jni=$enableval], - [use_jni=auto]) + [use_jni=no]) AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) @@ -154,6 +159,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], [ AC_MSG_RESULT([no]) ]) +if test x"$enable_coverage" = x"yes"; then + AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) + CFLAGS="$CFLAGS -O0 --coverage" + LDFLAGS="--coverage" +else + CFLAGS="$CFLAGS -O3" +fi + if test x"$use_ecmult_static_precomputation" != x"no"; then save_cross_compiling=$cross_compiling cross_compiling=no @@ -381,9 +394,6 @@ fi if test x"$use_jni" != x"no"; then AX_JNI_INCLUDE_DIR have_jni_dependencies=yes - if test x"$enable_module_schnorr" = x"no"; then - have_jni_dependencies=no - fi if test x"$enable_module_ecdh" = x"no"; then have_jni_dependencies=no fi @@ -392,7 +402,7 @@ if test x"$use_jni" != x"no"; then fi if test "x$have_jni_dependencies" = "xno"; then if test x"$use_jni" = x"yes"; then - AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and Schnorr and try again.]) + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) fi AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) use_jni=no @@ -421,10 +431,6 @@ if test x"$enable_module_ecdh" = x"yes"; then AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) fi -if test x"$enable_module_schnorr" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_SCHNORR, 1, [Define this symbol to enable the Schnorr signature module]) -fi - if test x"$enable_module_recovery" = x"yes"; then AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) fi @@ -441,8 +447,9 @@ AC_MSG_NOTICE([Using field implementation: $set_field]) AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) +AC_MSG_NOTICE([Building benchmarks: $use_benchmark]) +AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) -AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) AC_MSG_NOTICE([Using jni: $use_jni]) @@ -451,12 +458,8 @@ if test x"$enable_experimental" = x"yes"; then AC_MSG_NOTICE([WARNING: experimental build]) AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) - AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([******]) else - if test x"$enable_module_schnorr" = x"yes"; then - AC_MSG_ERROR([Schnorr signature module is experimental. Use --enable-experimental to allow.]) - fi if test x"$enable_module_ecdh" = x"yes"; then AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) fi @@ -472,11 +475,12 @@ AC_SUBST(SECP_INCLUDES) AC_SUBST(SECP_LIBS) AC_SUBST(SECP_TEST_LIBS) AC_SUBST(SECP_TEST_INCLUDES) +AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) +AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h index 6d27871a..7eaf63bf 100644 --- a/src/secp256k1/contrib/lax_der_parsing.h +++ b/src/secp256k1/contrib/lax_der_parsing.h @@ -48,14 +48,14 @@ * 8.3.1. */ -#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ -#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H +#define SECP256K1_CONTRIB_LAX_DER_PARSING_H #include -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Parse a signature in "lax DER" format * @@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax( } #endif -#endif +#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h index 2fd088f8..fece261f 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -25,14 +25,14 @@ * library are sufficient. */ -#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ -#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ +#ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H +#define SECP256K1_CONTRIB_BER_PRIVATEKEY_H #include -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Export a private key in DER format. * @@ -87,4 +87,4 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( } #endif -#endif +#endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h index f268e309..5c109f48 100644 --- a/src/secp256k1/include/secp256k1.h +++ b/src/secp256k1/include/secp256k1.h @@ -1,9 +1,9 @@ -#ifndef _SECP256K1_ -# define _SECP256K1_ +#ifndef SECP256K1_H +#define SECP256K1_H -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif #include @@ -42,6 +42,19 @@ extern "C" { */ typedef struct secp256k1_context_struct secp256k1_context; +/** Opaque data structure that holds rewriteable "scratch space" + * + * The purpose of this structure is to replace dynamic memory allocations, + * because we target architectures where this may not be available. It is + * essentially a resizable (within specified parameters) block of bytes, + * which is initially created either by memory allocation or TODO as a pointer + * into some fixed rewritable space. + * + * Unlike the context object, this cannot safely be shared between threads + * without additional synchronization logic. + */ +typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; + /** Opaque data structure that holds a parsed and valid public key. * * The exact representation of data inside is implementation defined and not @@ -61,7 +74,7 @@ typedef struct { * however guaranteed to be 64 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage, transmission, or * comparison, use the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_serialize_* functions. + * secp256k1_ecdsa_signature_parse_* functions. */ typedef struct { unsigned char data[64]; @@ -159,10 +172,19 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) +/** Prefix byte used to tag various encoded curvepoints for specific purposes */ +#define SECP256K1_TAG_PUBKEY_EVEN 0x02 +#define SECP256K1_TAG_PUBKEY_ODD 0x03 +#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 +#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 +#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 + /** Create a secp256k1 context object. * * Returns: a newly created context object. * In: flags: which parts of the context to initialize. + * + * See also secp256k1_context_randomize. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags @@ -234,6 +256,28 @@ SECP256K1_API void secp256k1_context_set_error_callback( const void* data ) SECP256K1_ARG_NONNULL(1); +/** Create a secp256k1 scratch space object. + * + * Returns: a newly created scratch space. + * Args: ctx: an existing context object (cannot be NULL) + * In: init_size: initial amount of memory to allocate + * max_size: maximum amount of memory to allocate + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create( + const secp256k1_context* ctx, + size_t init_size, + size_t max_size +) SECP256K1_ARG_NONNULL(1); + +/** Destroy a secp256k1 scratch space. + * + * The pointer may not be used afterwards. + * Args: scratch: space to destroy + */ +SECP256K1_API void secp256k1_scratch_space_destroy( + secp256k1_scratch_space* scratch +); + /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. @@ -485,6 +529,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Negates a private key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( + const secp256k1_context* ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Negates a public key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + /** Tweak a private key by adding tweak to it. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or if the resulting private key @@ -543,11 +609,24 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization. +/** Updates the context randomization to protect against side-channel leakage. * Returns: 1: randomization successfully updated * 0: error * Args: ctx: pointer to a context object (cannot be NULL) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + * + * While secp256k1 code is written to be constant-time no matter what secret + * values are, it's possible that a future compiler may output code which isn't, + * and also that the CPU may not emit the same radio frequencies or draw the same + * amount power for all values. + * + * This function provides a seed which is combined into the blinding value: that + * blinding value is added before each multiplication (and removed afterwards) so + * that it does not affect function results, but shields against attacks which + * rely on any input-dependent behaviour. + * + * You should call this after secp256k1_context_create or + * secp256k1_context_clone, and may call this repeatedly afterwards. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( secp256k1_context* ctx, @@ -570,8 +649,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( size_t n ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -# ifdef __cplusplus +#ifdef __cplusplus } -# endif - #endif + +#endif /* SECP256K1_H */ diff --git a/src/secp256k1/include/secp256k1_ecdh.h b/src/secp256k1/include/secp256k1_ecdh.h index 4b84d7a9..88492dc1 100644 --- a/src/secp256k1/include/secp256k1_ecdh.h +++ b/src/secp256k1/include/secp256k1_ecdh.h @@ -1,11 +1,11 @@ -#ifndef _SECP256K1_ECDH_ -# define _SECP256K1_ECDH_ +#ifndef SECP256K1_ECDH_H +#define SECP256K1_ECDH_H -# include "secp256k1.h" +#include "secp256k1.h" -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Compute an EC Diffie-Hellman secret in constant time * Returns: 1: exponentiation was successful @@ -24,8 +24,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( const unsigned char *privkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -# ifdef __cplusplus +#ifdef __cplusplus } -# endif - #endif + +#endif /* SECP256K1_ECDH_H */ diff --git a/src/secp256k1/include/secp256k1_recovery.h b/src/secp256k1/include/secp256k1_recovery.h index 05537972..cf6c5ed7 100644 --- a/src/secp256k1/include/secp256k1_recovery.h +++ b/src/secp256k1/include/secp256k1_recovery.h @@ -1,11 +1,11 @@ -#ifndef _SECP256K1_RECOVERY_ -# define _SECP256K1_RECOVERY_ +#ifndef SECP256K1_RECOVERY_H +#define SECP256K1_RECOVERY_H -# include "secp256k1.h" +#include "secp256k1.h" -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Opaque data structured that holds a parsed ECDSA signature, * supporting pubkey recovery. @@ -103,8 +103,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( const unsigned char *msg32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -# ifdef __cplusplus +#ifdef __cplusplus } -# endif - #endif + +#endif /* SECP256K1_RECOVERY_H */ diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage index ab580c5b..8521f079 100644 --- a/src/secp256k1/sage/group_prover.sage +++ b/src/secp256k1/sage/group_prover.sage @@ -3,7 +3,7 @@ # to independently set assumptions on input or intermediary variables. # # The general approach is: -# * A constraint is a tuple of two sets of of symbolic expressions: +# * A constraint is a tuple of two sets of symbolic expressions: # the first of which are required to evaluate to zero, the second of which # are required to evaluate to nonzero. # - A constraint is said to be conflicting if any of its nonzero expressions @@ -17,7 +17,7 @@ # - A constraint describing the requirements of the law, called "require" # * Implementations are transliterated into functions that operate as well on # algebraic input points, and are called once per combination of branches -# exectured. Each execution returns: +# executed. Each execution returns: # - A constraint describing the assumptions this implementation requires # (such as Z1=1), called "assumeFormula" # - A constraint describing the assumptions this specific branch requires, diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s index 5df561f2..5a9cc3ff 100644 --- a/src/secp256k1/src/asm/field_10x26_arm.s +++ b/src/secp256k1/src/asm/field_10x26_arm.s @@ -11,7 +11,7 @@ Note: - To avoid unnecessary loads and make use of available registers, two 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the the even passes + which will be added to c and d respectively in the even passes */ @@ -23,7 +23,7 @@ Note: .eabi_attribute 10, 0 @ Tag_FP_arch = none .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP - .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed + .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 .text diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h index c4c16eb7..fc588061 100644 --- a/src/secp256k1/src/basic-config.h +++ b/src/secp256k1/src/basic-config.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_BASIC_CONFIG_ -#define _SECP256K1_BASIC_CONFIG_ +#ifndef SECP256K1_BASIC_CONFIG_H +#define SECP256K1_BASIC_CONFIG_H #ifdef USE_BASIC_CONFIG @@ -28,5 +28,6 @@ #define USE_FIELD_10X26 1 #define USE_SCALAR_8X32 1 -#endif // USE_BASIC_CONFIG -#endif // _SECP256K1_BASIC_CONFIG_ +#endif /* USE_BASIC_CONFIG */ + +#endif /* SECP256K1_BASIC_CONFIG_H */ diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index 3a71b4aa..5b59783f 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -4,10 +4,11 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_BENCH_H_ -#define _SECP256K1_BENCH_H_ +#ifndef SECP256K1_BENCH_H +#define SECP256K1_BENCH_H #include +#include #include #include "sys/time.h" @@ -23,7 +24,7 @@ void print_number(double x) { if (y < 0.0) { y = -y; } - while (y < 100.0) { + while (y > 0 && y < 100.0) { y *= 10.0; c++; } @@ -63,4 +64,19 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v printf("us\n"); } -#endif +int have_flag(int argc, char** argv, char *flag) { + char** argm = argv + argc; + argv++; + if (argv == argm) { + return 1; + } + while (argv != NULL && argv != argm) { + if (strcmp(*argv, flag) == 0) { + return 1; + } + argv++; + } + return 0; +} + +#endif /* SECP256K1_BENCH_H */ diff --git a/src/secp256k1/src/bench_ecdh.c b/src/secp256k1/src/bench_ecdh.c index cde5e2db..5837f4e7 100644 --- a/src/secp256k1/src/bench_ecdh.c +++ b/src/secp256k1/src/bench_ecdh.c @@ -15,11 +15,11 @@ typedef struct { secp256k1_context *ctx; secp256k1_pubkey point; unsigned char scalar[32]; -} bench_ecdh_t; +} bench_ecdh_data; static void bench_ecdh_setup(void* arg) { int i; - bench_ecdh_t *data = (bench_ecdh_t*)arg; + bench_ecdh_data *data = (bench_ecdh_data*)arg; const unsigned char point[] = { 0x03, 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, @@ -39,7 +39,7 @@ static void bench_ecdh_setup(void* arg) { static void bench_ecdh(void* arg) { int i; unsigned char res[32]; - bench_ecdh_t *data = (bench_ecdh_t*)arg; + bench_ecdh_data *data = (bench_ecdh_data*)arg; for (i = 0; i < 20000; i++) { CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); @@ -47,7 +47,7 @@ static void bench_ecdh(void* arg) { } int main(void) { - bench_ecdh_t data; + bench_ecdh_data data; run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); return 0; diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c new file mode 100644 index 00000000..3a7bfe37 --- /dev/null +++ b/src/secp256k1/src/bench_ecmult.c @@ -0,0 +1,196 @@ +/********************************************************************** + * Copyright (c) 2017 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include + +#include "include/secp256k1.h" + +#include "util.h" +#include "hash_impl.h" +#include "num_impl.h" +#include "field_impl.h" +#include "group_impl.h" +#include "scalar_impl.h" +#include "ecmult_impl.h" +#include "bench.h" +#include "secp256k1.c" + +#define POINTS 32768 +#define ITERS 10000 + +typedef struct { + /* Setup once in advance */ + secp256k1_context* ctx; + secp256k1_scratch_space* scratch; + secp256k1_scalar* scalars; + secp256k1_ge* pubkeys; + secp256k1_scalar* seckeys; + secp256k1_gej* expected_output; + secp256k1_ecmult_multi_func ecmult_multi; + + /* Changes per test */ + size_t count; + int includes_g; + + /* Changes per test iteration */ + size_t offset1; + size_t offset2; + + /* Test output. */ + secp256k1_gej* output; +} bench_data; + +static int bench_callback(secp256k1_scalar* sc, secp256k1_ge* ge, size_t idx, void* arg) { + bench_data* data = (bench_data*)arg; + if (data->includes_g) ++idx; + if (idx == 0) { + *sc = data->scalars[data->offset1]; + *ge = secp256k1_ge_const_g; + } else { + *sc = data->scalars[(data->offset1 + idx) % POINTS]; + *ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS]; + } + return 1; +} + +static void bench_ecmult(void* arg) { + bench_data* data = (bench_data*)arg; + + size_t count = data->count; + int includes_g = data->includes_g; + size_t iters = 1 + ITERS / count; + size_t iter; + + for (iter = 0; iter < iters; ++iter) { + data->ecmult_multi(&data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_callback, arg, count - includes_g); + data->offset1 = (data->offset1 + count) % POINTS; + data->offset2 = (data->offset2 + count - 1) % POINTS; + } +} + +static void bench_ecmult_setup(void* arg) { + bench_data* data = (bench_data*)arg; + data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS; + data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS; +} + +static void bench_ecmult_teardown(void* arg) { + bench_data* data = (bench_data*)arg; + size_t iters = 1 + ITERS / data->count; + size_t iter; + /* Verify the results in teardown, to avoid doing comparisons while benchmarking. */ + for (iter = 0; iter < iters; ++iter) { + secp256k1_gej tmp; + secp256k1_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); + CHECK(secp256k1_gej_is_infinity(&tmp)); + } +} + +static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { + secp256k1_sha256 sha256; + unsigned char c[11] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0}; + unsigned char buf[32]; + int overflow = 0; + c[6] = num; + c[7] = num >> 8; + c[8] = num >> 16; + c[9] = num >> 24; + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, c, sizeof(c)); + secp256k1_sha256_finalize(&sha256, buf); + secp256k1_scalar_set_b32(scalar, buf, &overflow); + CHECK(!overflow); +} + +static void run_test(bench_data* data, size_t count, int includes_g) { + char str[32]; + static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + size_t iters = 1 + ITERS / count; + size_t iter; + + data->count = count; + data->includes_g = includes_g; + + /* Compute (the negation of) the expected results directly. */ + data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS; + data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS; + for (iter = 0; iter < iters; ++iter) { + secp256k1_scalar tmp; + secp256k1_scalar total = data->scalars[(data->offset1++) % POINTS]; + size_t i = 0; + for (i = 0; i + 1 < count; ++i) { + secp256k1_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); + secp256k1_scalar_add(&total, &total, &tmp); + } + secp256k1_scalar_negate(&total, &total); + secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total); + } + + /* Run the benchmark. */ + sprintf(str, includes_g ? "ecmult_%ig" : "ecmult_%i", (int)count); + run_benchmark(str, bench_ecmult, bench_ecmult_setup, bench_ecmult_teardown, data, 10, count * (1 + ITERS / count)); +} + +int main(int argc, char **argv) { + bench_data data; + int i, p; + secp256k1_gej* pubkeys_gej; + size_t scratch_size; + + if (argc > 1) { + if(have_flag(argc, argv, "pippenger_wnaf")) { + printf("Using pippenger_wnaf:\n"); + data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single; + } else if(have_flag(argc, argv, "strauss_wnaf")) { + printf("Using strauss_wnaf:\n"); + data.ecmult_multi = secp256k1_ecmult_strauss_batch_single; + } + } else { + data.ecmult_multi = secp256k1_ecmult_multi_var; + } + + /* Allocate stuff */ + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; + data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size, scratch_size); + data.scalars = malloc(sizeof(secp256k1_scalar) * POINTS); + data.seckeys = malloc(sizeof(secp256k1_scalar) * POINTS); + data.pubkeys = malloc(sizeof(secp256k1_ge) * POINTS); + data.expected_output = malloc(sizeof(secp256k1_gej) * (ITERS + 1)); + data.output = malloc(sizeof(secp256k1_gej) * (ITERS + 1)); + + /* Generate a set of scalars, and private/public keypairs. */ + pubkeys_gej = malloc(sizeof(secp256k1_gej) * POINTS); + secp256k1_gej_set_ge(&pubkeys_gej[0], &secp256k1_ge_const_g); + secp256k1_scalar_set_int(&data.seckeys[0], 1); + for (i = 0; i < POINTS; ++i) { + generate_scalar(i, &data.scalars[i]); + if (i) { + secp256k1_gej_double_var(&pubkeys_gej[i], &pubkeys_gej[i - 1], NULL); + secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); + } + } + secp256k1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS, &data.ctx->error_callback); + free(pubkeys_gej); + + for (i = 1; i <= 8; ++i) { + run_test(&data, i, 1); + } + + for (p = 0; p <= 11; ++p) { + for (i = 9; i <= 16; ++i) { + run_test(&data, i << p, 1); + } + } + secp256k1_context_destroy(data.ctx); + secp256k1_scratch_space_destroy(data.scratch); + free(data.scalars); + free(data.pubkeys); + free(data.seckeys); + free(data.output); + free(data.expected_output); + + return(0); +} diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c index 0809f77b..996aa8b0 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -25,10 +25,10 @@ typedef struct { secp256k1_gej gej_x, gej_y; unsigned char data[64]; int wnaf[256]; -} bench_inv_t; +} bench_inv; void bench_setup(void* arg) { - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; static const unsigned char init_x[32] = { 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, @@ -58,7 +58,7 @@ void bench_setup(void* arg) { void bench_scalar_add(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); @@ -67,7 +67,7 @@ void bench_scalar_add(void* arg) { void bench_scalar_negate(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); @@ -76,7 +76,7 @@ void bench_scalar_negate(void* arg) { void bench_scalar_sqr(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); @@ -85,7 +85,7 @@ void bench_scalar_sqr(void* arg) { void bench_scalar_mul(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); @@ -95,7 +95,7 @@ void bench_scalar_mul(void* arg) { #ifdef USE_ENDOMORPHISM void bench_scalar_split(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_scalar l, r; @@ -107,7 +107,7 @@ void bench_scalar_split(void* arg) { void bench_scalar_inverse(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); @@ -117,7 +117,7 @@ void bench_scalar_inverse(void* arg) { void bench_scalar_inverse_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); @@ -127,7 +127,7 @@ void bench_scalar_inverse_var(void* arg) { void bench_field_normalize(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize(&data->fe_x); @@ -136,7 +136,7 @@ void bench_field_normalize(void* arg) { void bench_field_normalize_weak(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize_weak(&data->fe_x); @@ -145,7 +145,7 @@ void bench_field_normalize_weak(void* arg) { void bench_field_mul(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); @@ -154,7 +154,7 @@ void bench_field_mul(void* arg) { void bench_field_sqr(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_sqr(&data->fe_x, &data->fe_x); @@ -163,7 +163,7 @@ void bench_field_sqr(void* arg) { void bench_field_inverse(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv(&data->fe_x, &data->fe_x); @@ -173,7 +173,7 @@ void bench_field_inverse(void* arg) { void bench_field_inverse_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); @@ -183,7 +183,7 @@ void bench_field_inverse_var(void* arg) { void bench_field_sqrt(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); @@ -193,7 +193,7 @@ void bench_field_sqrt(void* arg) { void bench_group_double_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); @@ -202,7 +202,7 @@ void bench_group_double_var(void* arg) { void bench_group_add_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); @@ -211,7 +211,7 @@ void bench_group_add_var(void* arg) { void bench_group_add_affine(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); @@ -220,7 +220,7 @@ void bench_group_add_affine(void* arg) { void bench_group_add_affine_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); @@ -229,7 +229,7 @@ void bench_group_add_affine_var(void* arg) { void bench_group_jacobi_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_gej_has_quad_y_var(&data->gej_x); @@ -238,7 +238,7 @@ void bench_group_jacobi_var(void* arg) { void bench_ecmult_wnaf(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); @@ -248,7 +248,7 @@ void bench_ecmult_wnaf(void* arg) { void bench_wnaf_const(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); @@ -259,8 +259,8 @@ void bench_wnaf_const(void* arg) { void bench_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_sha256_t sha; + bench_inv *data = (bench_inv*)arg; + secp256k1_sha256 sha; for (i = 0; i < 20000; i++) { secp256k1_sha256_initialize(&sha); @@ -271,8 +271,8 @@ void bench_sha256(void* arg) { void bench_hmac_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_hmac_sha256_t hmac; + bench_inv *data = (bench_inv*)arg; + secp256k1_hmac_sha256 hmac; for (i = 0; i < 20000; i++) { secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); @@ -283,8 +283,8 @@ void bench_hmac_sha256(void* arg) { void bench_rfc6979_hmac_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_rfc6979_hmac_sha256_t rng; + bench_inv *data = (bench_inv*)arg; + secp256k1_rfc6979_hmac_sha256 rng; for (i = 0; i < 20000; i++) { secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); @@ -311,7 +311,7 @@ void bench_context_sign(void* arg) { #ifndef USE_NUM_NONE void bench_num_jacobi(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; secp256k1_num nx, norder; secp256k1_scalar_get_num(&nx, &data->scalar_x); @@ -324,23 +324,8 @@ void bench_num_jacobi(void* arg) { } #endif -int have_flag(int argc, char** argv, char *flag) { - char** argm = argv + argc; - argv++; - if (argv == argm) { - return 1; - } - while (argv != NULL && argv != argm) { - if (strcmp(*argv, flag) == 0) { - return 1; - } - argv++; - } - return 0; -} - int main(int argc, char **argv) { - bench_inv_t data; + bench_inv data; if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c index 6489378c..b806eed9 100644 --- a/src/secp256k1/src/bench_recover.c +++ b/src/secp256k1/src/bench_recover.c @@ -13,11 +13,11 @@ typedef struct { secp256k1_context *ctx; unsigned char msg[32]; unsigned char sig[64]; -} bench_recover_t; +} bench_recover_data; void bench_recover(void* arg) { int i; - bench_recover_t *data = (bench_recover_t*)arg; + bench_recover_data *data = (bench_recover_data*)arg; secp256k1_pubkey pubkey; unsigned char pubkeyc[33]; @@ -38,7 +38,7 @@ void bench_recover(void* arg) { void bench_recover_setup(void* arg) { int i; - bench_recover_t *data = (bench_recover_t*)arg; + bench_recover_data *data = (bench_recover_data*)arg; for (i = 0; i < 32; i++) { data->msg[i] = 1 + i; @@ -49,7 +49,7 @@ void bench_recover_setup(void* arg) { } int main(void) { - bench_recover_t data; + bench_recover_data data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c index ed7224d7..544b4396 100644 --- a/src/secp256k1/src/bench_sign.c +++ b/src/secp256k1/src/bench_sign.c @@ -12,11 +12,11 @@ typedef struct { secp256k1_context* ctx; unsigned char msg[32]; unsigned char key[32]; -} bench_sign_t; +} bench_sign; static void bench_sign_setup(void* arg) { int i; - bench_sign_t *data = (bench_sign_t*)arg; + bench_sign *data = (bench_sign*)arg; for (i = 0; i < 32; i++) { data->msg[i] = i + 1; @@ -26,9 +26,9 @@ static void bench_sign_setup(void* arg) { } } -static void bench_sign(void* arg) { +static void bench_sign_run(void* arg) { int i; - bench_sign_t *data = (bench_sign_t*)arg; + bench_sign *data = (bench_sign*)arg; unsigned char sig[74]; for (i = 0; i < 20000; i++) { @@ -45,11 +45,11 @@ static void bench_sign(void* arg) { } int main(void) { - bench_sign_t data; + bench_sign data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); + run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, 20000); secp256k1_context_destroy(data.ctx); return 0; diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h index 54ae101b..80590c7c 100644 --- a/src/secp256k1/src/ecdsa.h +++ b/src/secp256k1/src/ecdsa.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECDSA_ -#define _SECP256K1_ECDSA_ +#ifndef SECP256K1_ECDSA_H +#define SECP256K1_ECDSA_H #include @@ -18,4 +18,4 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); -#endif +#endif /* SECP256K1_ECDSA_H */ diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h index d110b4bb..c3400042 100644 --- a/src/secp256k1/src/ecdsa_impl.h +++ b/src/secp256k1/src/ecdsa_impl.h @@ -5,8 +5,8 @@ **********************************************************************/ -#ifndef _SECP256K1_ECDSA_IMPL_H_ -#define _SECP256K1_ECDSA_IMPL_H_ +#ifndef SECP256K1_ECDSA_IMPL_H +#define SECP256K1_ECDSA_IMPL_H #include "scalar.h" #include "field.h" @@ -81,8 +81,6 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha return -1; } while (lenleft > 0) { - if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { - } ret = (ret << 8) | **sigp; if (ret + lenleft > (size_t)(sigend - *sigp)) { /* Result exceeds the length of the passed array. */ @@ -203,7 +201,9 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { unsigned char c[32]; secp256k1_scalar sn, u1, u2; +#if !defined(EXHAUSTIVE_TEST_ORDER) secp256k1_fe xr; +#endif secp256k1_gej pubkeyj; secp256k1_gej pr; @@ -219,6 +219,19 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const if (secp256k1_gej_is_infinity(&pr)) { return 0; } + +#if defined(EXHAUSTIVE_TEST_ORDER) +{ + secp256k1_scalar computed_r; + secp256k1_ge pr_ge; + secp256k1_ge_set_gej(&pr_ge, &pr); + secp256k1_fe_normalize(&pr_ge.x); + + secp256k1_fe_get_b32(c, &pr_ge.x); + secp256k1_scalar_set_b32(&computed_r, c, NULL); + return secp256k1_scalar_eq(sigr, &computed_r); +} +#else secp256k1_scalar_get_b32(c, sigr); secp256k1_fe_set_b32(&xr, c); @@ -252,6 +265,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const return 1; } return 0; +#endif } static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { @@ -267,14 +281,10 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); secp256k1_scalar_set_b32(sigr, b, &overflow); - if (secp256k1_scalar_is_zero(sigr)) { - /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. - * This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. - */ - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - return 0; - } + /* These two conditions should be checked before calling */ + VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); + VERIFY_CHECK(overflow == 0); + if (recid) { /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. @@ -300,4 +310,4 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec return 1; } -#endif +#endif /* SECP256K1_ECDSA_IMPL_H */ diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h index 42739a3b..b621f1e6 100644 --- a/src/secp256k1/src/eckey.h +++ b/src/secp256k1/src/eckey.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECKEY_ -#define _SECP256K1_ECKEY_ +#ifndef SECP256K1_ECKEY_H +#define SECP256K1_ECKEY_H #include @@ -22,4 +22,4 @@ static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); -#endif +#endif /* SECP256K1_ECKEY_H */ diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h index ce38071a..1ab9a68e 100644 --- a/src/secp256k1/src/eckey_impl.h +++ b/src/secp256k1/src/eckey_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECKEY_IMPL_H_ -#define _SECP256K1_ECKEY_IMPL_H_ +#ifndef SECP256K1_ECKEY_IMPL_H +#define SECP256K1_ECKEY_IMPL_H #include "eckey.h" @@ -15,16 +15,17 @@ #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { - if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { secp256k1_fe x; - return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); + return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { secp256k1_fe x, y; if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { return 0; } secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { + if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && + secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { return 0; } return secp256k1_ge_is_valid_var(elem); @@ -42,10 +43,10 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p secp256k1_fe_get_b32(&pub[1], &elem->x); if (compressed) { *size = 33; - pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; } else { *size = 65; - pub[0] = 0x04; + pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; secp256k1_fe_get_b32(&pub[33], &elem->y); } return 1; @@ -96,4 +97,4 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, return 1; } -#endif +#endif /* SECP256K1_ECKEY_IMPL_H */ diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h index 20484134..ea1cd8a2 100644 --- a/src/secp256k1/src/ecmult.h +++ b/src/secp256k1/src/ecmult.h @@ -1,14 +1,16 @@ /********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_ -#define _SECP256K1_ECMULT_ +#ifndef SECP256K1_ECMULT_H +#define SECP256K1_ECMULT_H #include "num.h" #include "group.h" +#include "scalar.h" +#include "scratch.h" typedef struct { /* For accelerating the computation of a*P + b*G: */ @@ -28,4 +30,18 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx /** Double multiply: R = na*A + ng*G */ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); -#endif +typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); + +/** + * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. + * Chooses the right algorithm for a given number of points and scratch space + * size. Resets and overwrites the given scratch space. If the points do not + * fit in the scratch space the algorithm is repeatedly run with batches of + * points. + * Returns: 1 on success (including when inp_g_sc is NULL and n is 0) + * 0 if there is not enough scratch space for a single point or + * callback returns 0 + */ +static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); + +#endif /* SECP256K1_ECMULT_H */ diff --git a/src/secp256k1/src/ecmult_const.h b/src/secp256k1/src/ecmult_const.h index 2b009765..72bf7d75 100644 --- a/src/secp256k1/src/ecmult_const.h +++ b/src/secp256k1/src/ecmult_const.h @@ -4,12 +4,12 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_CONST_ -#define _SECP256K1_ECMULT_CONST_ +#ifndef SECP256K1_ECMULT_CONST_H +#define SECP256K1_ECMULT_CONST_H #include "scalar.h" #include "group.h" static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); -#endif +#endif /* SECP256K1_ECMULT_CONST_H */ diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h index 7a6a2531..fae50020 100644 --- a/src/secp256k1/src/ecmult_const_impl.h +++ b/src/secp256k1/src/ecmult_const_impl.h @@ -4,21 +4,14 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_CONST_IMPL_ -#define _SECP256K1_ECMULT_CONST_IMPL_ +#ifndef SECP256K1_ECMULT_CONST_IMPL_H +#define SECP256K1_ECMULT_CONST_IMPL_H #include "scalar.h" #include "group.h" #include "ecmult_const.h" #include "ecmult_impl.h" -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) - /* This is like `ECMULT_TABLE_GET_GE` but is constant time */ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ int m; \ @@ -42,11 +35,12 @@ } while(0) -/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) - * with the following guarantees: +/** Convert a number to WNAF notation. + * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. + * It has the following guarantees: * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) * - each wnaf[i] is nonzero - * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w + * - the number of words set is always WNAF_SIZE(w) + 1 * * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) @@ -78,7 +72,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { /* Negative numbers will be negated to keep their bit representation below the maximum width */ flip = secp256k1_scalar_is_high(&s); /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ (s.d[0] & 1); + bit = flip ^ !secp256k1_scalar_is_even(&s); /* We check for negative one, since adding 2 to it will cause an overflow */ secp256k1_scalar_negate(&neg_s, &s); not_neg_one = !secp256k1_scalar_is_one(&neg_s); @@ -236,4 +230,4 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons } } -#endif +#endif /* SECP256K1_ECMULT_CONST_IMPL_H */ diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h index eb2cc9ea..7564b701 100644 --- a/src/secp256k1/src/ecmult_gen.h +++ b/src/secp256k1/src/ecmult_gen.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_GEN_ -#define _SECP256K1_ECMULT_GEN_ +#ifndef SECP256K1_ECMULT_GEN_H +#define SECP256K1_ECMULT_GEN_H #include "scalar.h" #include "group.h" @@ -40,4 +40,4 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp25 static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); -#endif +#endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h index 35f25460..714f02e9 100644 --- a/src/secp256k1/src/ecmult_gen_impl.h +++ b/src/secp256k1/src/ecmult_gen_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ -#define _SECP256K1_ECMULT_GEN_IMPL_H_ +#ifndef SECP256K1_ECMULT_GEN_IMPL_H +#define SECP256K1_ECMULT_GEN_IMPL_H #include "scalar.h" #include "group.h" @@ -161,7 +161,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_gej gb; secp256k1_fe s; unsigned char nonce32[32]; - secp256k1_rfc6979_hmac_sha256_t rng; + secp256k1_rfc6979_hmac_sha256 rng; int retry; unsigned char keydata[64] = {0}; if (seed32 == NULL) { @@ -207,4 +207,4 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_gej_clear(&gb); } -#endif +#endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index d1e83bd6..fd14bf12 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1,21 +1,36 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/***************************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + *****************************************************************************/ -#ifndef _SECP256K1_ECMULT_IMPL_H_ -#define _SECP256K1_ECMULT_IMPL_H_ +#ifndef SECP256K1_ECMULT_IMPL_H +#define SECP256K1_ECMULT_IMPL_H + +#include +#include #include "group.h" #include "scalar.h" #include "ecmult.h" -#include - +#if defined(EXHAUSTIVE_TEST_ORDER) +/* We need to lower these values for exhaustive tests because + * the tables cannot have infinities in them (this breaks the + * affine-isomorphism stuff which tracks z-ratios) */ +# if EXHAUSTIVE_TEST_ORDER > 128 +# define WINDOW_A 5 +# define WINDOW_G 8 +# elif EXHAUSTIVE_TEST_ORDER > 8 +# define WINDOW_A 4 +# define WINDOW_G 4 +# else +# define WINDOW_A 2 +# define WINDOW_G 2 +# endif +#else /* optimal for 128-bit and 256-bit exponents. */ #define WINDOW_A 5 - /** larger numbers may result in slightly better performance, at the cost of exponentially larger precomputed tables. */ #ifdef USE_ENDOMORPHISM @@ -25,10 +40,37 @@ /** One table for window size 16: 1.375 MiB. */ #define WINDOW_G 16 #endif +#endif + +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) /** The number of entries a table with precomputed multiples needs to have. */ #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) +/* The number of objects allocated on the scratch space for ecmult_multi algorithms */ +#define PIPPENGER_SCRATCH_OBJECTS 6 +#define STRAUSS_SCRATCH_OBJECTS 6 + +#define PIPPENGER_MAX_BUCKET_WINDOW 12 + +/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */ +#ifdef USE_ENDOMORPHISM + #define ECMULT_PIPPENGER_THRESHOLD 88 +#else + #define ECMULT_PIPPENGER_THRESHOLD 160 +#endif + +#ifdef USE_ENDOMORPHISM + #define ECMULT_MAX_POINTS_PER_BATCH 5000000 +#else + #define ECMULT_MAX_POINTS_PER_BATCH 10000000 +#endif + /** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. @@ -268,50 +310,78 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, return last_set_bit + 1; } -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; +struct secp256k1_strauss_point_state { #ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_scalar na_1, na_lam; - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; int wnaf_na_1[130]; int wnaf_na_lam[130]; int bits_na_1; int bits_na_lam; - int wnaf_ng_1[129]; - int bits_ng_1; - int wnaf_ng_128[129]; - int bits_ng_128; #else int wnaf_na[256]; int bits_na; +#endif + size_t input_pos; +}; + +struct secp256k1_strauss_state { + secp256k1_gej* prej; + secp256k1_fe* zr; + secp256k1_ge* pre_a; +#ifdef USE_ENDOMORPHISM + secp256k1_ge* pre_a_lam; +#endif + struct secp256k1_strauss_point_state* ps; +}; + +static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { + secp256k1_ge tmpa; + secp256k1_fe Z; +#ifdef USE_ENDOMORPHISM + /* Splitted G factors. */ + secp256k1_scalar ng_1, ng_128; + int wnaf_ng_1[129]; + int bits_ng_1 = 0; + int wnaf_ng_128[129]; + int bits_ng_128 = 0; +#else int wnaf_ng[256]; - int bits_ng; + int bits_ng = 0; #endif int i; - int bits; + int bits = 0; + int np; + int no = 0; + for (np = 0; np < num; ++np) { + if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) { + continue; + } + state->ps[no].input_pos = np; #ifdef USE_ENDOMORPHISM - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&na_1, &na_lam, na); - - /* build wnaf representation for na_1 and na_lam. */ - bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); - bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); - VERIFY_CHECK(bits_na_1 <= 130); - VERIFY_CHECK(bits_na_lam <= 130); - bits = bits_na_1; - if (bits_na_lam > bits) { - bits = bits_na_lam; - } + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]); + + /* build wnaf representation for na_1 and na_lam. */ + state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, WINDOW_A); + state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 130, &state->ps[no].na_lam, WINDOW_A); + VERIFY_CHECK(state->ps[no].bits_na_1 <= 130); + VERIFY_CHECK(state->ps[no].bits_na_lam <= 130); + if (state->ps[no].bits_na_1 > bits) { + bits = state->ps[no].bits_na_1; + } + if (state->ps[no].bits_na_lam > bits) { + bits = state->ps[no].bits_na_lam; + } #else - /* build wnaf representation for na. */ - bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); - bits = bits_na; + /* build wnaf representation for na. */ + state->ps[no].bits_na = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A); + if (state->ps[no].bits_na > bits) { + bits = state->ps[no].bits_na; + } #endif + ++no; + } /* Calculate odd multiples of a. * All multiples are brought to the same Z 'denominator', which is stored @@ -323,29 +393,51 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same * isomorphism to efficiently add with a known Z inverse. */ - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); + if (no > 0) { + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]); + for (np = 1; np < no; ++np) { + secp256k1_gej tmp = a[state->ps[np].input_pos]; +#ifdef VERIFY + secp256k1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); +#endif + secp256k1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); + secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &tmp); + secp256k1_fe_mul(state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &(a[state->ps[np].input_pos].z)); + } + /* Bring them to the same Z denominator. */ + secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr); + } else { + secp256k1_fe_set_int(&Z, 1); + } #ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + for (np = 0; np < no; ++np) { + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]); + } } - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); + if (ng) { + /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; + } } #else - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; + if (ng) { + bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; + } } #endif @@ -355,13 +447,15 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej int n; secp256k1_gej_double_var(r, r, NULL); #ifdef USE_ENDOMORPHISM - if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_na_lam && (n = wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + for (np = 0; np < no; ++np) { + if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) { + ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) { + ECMULT_TABLE_GET_GE(&tmpa, state->pre_a_lam + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } } if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); @@ -372,9 +466,11 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); } #else - if (i < bits_na && (n = wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + for (np = 0; np < no; ++np) { + if (i < state->ps[np].bits_na && (n = state->ps[np].wnaf_na[i])) { + ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } } if (i < bits_ng && (n = wnaf_ng[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); @@ -388,4 +484,528 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej } } +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { + secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + struct secp256k1_strauss_point_state ps[1]; +#ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; +#endif + struct secp256k1_strauss_state state; + + state.prej = prej; + state.zr = zr; + state.pre_a = pre_a; +#ifdef USE_ENDOMORPHISM + state.pre_a_lam = pre_a_lam; +#endif + state.ps = ps; + secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng); +} + +static size_t secp256k1_strauss_scratch_size(size_t n_points) { +#ifdef USE_ENDOMORPHISM + static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); +#else + static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); +#endif + return n_points*point_size; +} + +static int secp256k1_ecmult_strauss_batch(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { + secp256k1_gej* points; + secp256k1_scalar* scalars; + struct secp256k1_strauss_state state; + size_t i; + + secp256k1_gej_set_infinity(r); + if (inp_g_sc == NULL && n_points == 0) { + return 1; + } + + if (!secp256k1_scratch_resize(scratch, secp256k1_strauss_scratch_size(n_points), STRAUSS_SCRATCH_OBJECTS)) { + return 0; + } + secp256k1_scratch_reset(scratch); + points = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_gej)); + scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_scalar)); + state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej)); + state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe)); +#ifdef USE_ENDOMORPHISM + state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); + state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A); +#else + state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); +#endif + state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(scratch, n_points * sizeof(struct secp256k1_strauss_point_state)); + + for (i = 0; i < n_points; i++) { + secp256k1_ge point; + if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) return 0; + secp256k1_gej_set_ge(&points[i], &point); + } + secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); + return 1; +} + +/* Wrapper for secp256k1_ecmult_multi_func interface */ +static int secp256k1_ecmult_strauss_batch_single(const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { + return secp256k1_ecmult_strauss_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); +} + +static size_t secp256k1_strauss_max_points(secp256k1_scratch *scratch) { + return secp256k1_scratch_max_allocation(scratch, STRAUSS_SCRATCH_OBJECTS) / secp256k1_strauss_scratch_size(1); +} + +/** Convert a number to WNAF notation. + * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. + * It has the following guarantees: + * - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w) + * - the number of words set is always WNAF_SIZE(w) + * - the returned skew is 0 without endomorphism, or 0 or 1 with endomorphism + */ +static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) { + int sign = 0; + int skew = 0; + int pos = 1; +#ifndef USE_ENDOMORPHISM + secp256k1_scalar neg_s; #endif + const secp256k1_scalar *work = s; + + if (secp256k1_scalar_is_zero(s)) { + while (pos * w < WNAF_BITS) { + wnaf[pos] = 0; + ++pos; + } + return 0; + } + + if (secp256k1_scalar_is_even(s)) { +#ifdef USE_ENDOMORPHISM + skew = 1; +#else + secp256k1_scalar_negate(&neg_s, s); + work = &neg_s; + sign = -1; +#endif + } + + wnaf[0] = (secp256k1_scalar_get_bits_var(work, 0, w) + skew + sign) ^ sign; + + while (pos * w < WNAF_BITS) { + int now = w; + int val; + if (now + pos * w > WNAF_BITS) { + now = WNAF_BITS - pos * w; + } + val = secp256k1_scalar_get_bits_var(work, pos * w, now); + if ((val & 1) == 0) { + wnaf[pos - 1] -= ((1 << w) + sign) ^ sign; + wnaf[pos] = (val + 1 + sign) ^ sign; + } else { + wnaf[pos] = (val + sign) ^ sign; + } + ++pos; + } + VERIFY_CHECK(pos == WNAF_SIZE(w)); + + return skew; +} + +struct secp256k1_pippenger_point_state { + int skew_na; + size_t input_pos; +}; + +struct secp256k1_pippenger_state { + int *wnaf_na; + struct secp256k1_pippenger_point_state* ps; +}; + +/* + * pippenger_wnaf computes the result of a multi-point multiplication as + * follows: The scalars are brought into wnaf with n_wnaf elements each. Then + * for every i < n_wnaf, first each point is added to a "bucket" corresponding + * to the point's wnaf[i]. Second, the buckets are added together such that + * r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ... + */ +static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, secp256k1_scalar *sc, secp256k1_ge *pt, size_t num) { + size_t n_wnaf = WNAF_SIZE(bucket_window+1); + size_t np; + size_t no = 0; + int i; + int j; + + for (np = 0; np < num; ++np) { + if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { + continue; + } + state->ps[no].input_pos = np; + state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); + no++; + } + secp256k1_gej_set_infinity(r); + + if (no == 0) { + return 1; + } + + for (i = n_wnaf - 1; i >= 0; i--) { + secp256k1_gej running_sum; + + for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { + secp256k1_gej_set_infinity(&buckets[j]); + } + + for (np = 0; np < no; ++np) { + int n = state->wnaf_na[np*n_wnaf + i]; + struct secp256k1_pippenger_point_state point_state = state->ps[np]; + secp256k1_ge tmp; + int idx; + +#ifdef USE_ENDOMORPHISM + if (i == 0) { + /* correct for wnaf skew */ + int skew = point_state.skew_na; + if (skew) { + secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); + secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); + } + } +#endif + if (n > 0) { + idx = (n - 1)/2; + secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); + } else if (n < 0) { + idx = -(n + 1)/2; + secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); + secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); + } + } + + for(j = 0; j < bucket_window; j++) { + secp256k1_gej_double_var(r, r, NULL); + } + + secp256k1_gej_set_infinity(&running_sum); + /* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ... + * = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ... + * + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...) + * using an intermediate running sum: + * running_sum = bucket[0] + bucket[1] + bucket[2] + ... + * + * The doubling is done implicitly by deferring the final window doubling (of 'r'). + */ + for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { + secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); + secp256k1_gej_add_var(r, r, &running_sum, NULL); + } + + secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); + secp256k1_gej_double_var(r, r, NULL); + secp256k1_gej_add_var(r, r, &running_sum, NULL); + } + return 1; +} + +/** + * Returns optimal bucket_window (number of bits of a scalar represented by a + * set of buckets) for a given number of points. + */ +static int secp256k1_pippenger_bucket_window(size_t n) { +#ifdef USE_ENDOMORPHISM + if (n <= 1) { + return 1; + } else if (n <= 4) { + return 2; + } else if (n <= 20) { + return 3; + } else if (n <= 57) { + return 4; + } else if (n <= 136) { + return 5; + } else if (n <= 235) { + return 6; + } else if (n <= 1260) { + return 7; + } else if (n <= 4420) { + return 9; + } else if (n <= 7880) { + return 10; + } else if (n <= 16050) { + return 11; + } else { + return PIPPENGER_MAX_BUCKET_WINDOW; + } +#else + if (n <= 1) { + return 1; + } else if (n <= 11) { + return 2; + } else if (n <= 45) { + return 3; + } else if (n <= 100) { + return 4; + } else if (n <= 275) { + return 5; + } else if (n <= 625) { + return 6; + } else if (n <= 1850) { + return 7; + } else if (n <= 3400) { + return 8; + } else if (n <= 9630) { + return 9; + } else if (n <= 17900) { + return 10; + } else if (n <= 32800) { + return 11; + } else { + return PIPPENGER_MAX_BUCKET_WINDOW; + } +#endif +} + +/** + * Returns the maximum optimal number of points for a bucket_window. + */ +static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) { + switch(bucket_window) { +#ifdef USE_ENDOMORPHISM + case 1: return 1; + case 2: return 4; + case 3: return 20; + case 4: return 57; + case 5: return 136; + case 6: return 235; + case 7: return 1260; + case 8: return 1260; + case 9: return 4420; + case 10: return 7880; + case 11: return 16050; + case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; +#else + case 1: return 1; + case 2: return 11; + case 3: return 45; + case 4: return 100; + case 5: return 275; + case 6: return 625; + case 7: return 1850; + case 8: return 3400; + case 9: return 9630; + case 10: return 17900; + case 11: return 32800; + case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; +#endif + } + return 0; +} + + +#ifdef USE_ENDOMORPHISM +SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) { + secp256k1_scalar tmp = *s1; + secp256k1_scalar_split_lambda(s1, s2, &tmp); + secp256k1_ge_mul_lambda(p2, p1); + + if (secp256k1_scalar_is_high(s1)) { + secp256k1_scalar_negate(s1, s1); + secp256k1_ge_neg(p1, p1); + } + if (secp256k1_scalar_is_high(s2)) { + secp256k1_scalar_negate(s2, s2); + secp256k1_ge_neg(p2, p2); + } +} +#endif + +/** + * Returns the scratch size required for a given number of points (excluding + * base point G) without considering alignment. + */ +static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) { +#ifdef USE_ENDOMORPHISM + size_t entries = 2*n_points + 2; +#else + size_t entries = n_points + 1; +#endif + size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); + return ((1<ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(scratch, entries * sizeof(*state_space->ps)); + state_space->wnaf_na = (int *) secp256k1_scratch_alloc(scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); + buckets = (secp256k1_gej *) secp256k1_scratch_alloc(scratch, (1<ps[i].skew_na = 0; + for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) { + state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0; + } + } + for(i = 0; i < 1< max_alloc) { + break; + } + space_for_points = max_alloc - space_overhead; + + n_points = space_for_points/entry_size; + n_points = n_points > max_points ? max_points : n_points; + if (n_points > res) { + res = n_points; + } + if (n_points < max_points) { + /* A larger bucket_window may support even more points. But if we + * would choose that then the caller couldn't safely use any number + * smaller than what this function returns */ + break; + } + } + return res; +} + +typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t); +static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { + size_t i; + + int (*f)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t); + size_t max_points; + size_t n_batches; + size_t n_batch_points; + + secp256k1_gej_set_infinity(r); + if (inp_g_sc == NULL && n == 0) { + return 1; + } else if (n == 0) { + secp256k1_scalar szero; + secp256k1_scalar_set_int(&szero, 0); + secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc); + return 1; + } + + max_points = secp256k1_pippenger_max_points(scratch); + if (max_points == 0) { + return 0; + } else if (max_points > ECMULT_MAX_POINTS_PER_BATCH) { + max_points = ECMULT_MAX_POINTS_PER_BATCH; + } + n_batches = (n+max_points-1)/max_points; + n_batch_points = (n+n_batches-1)/n_batches; + + if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { + f = secp256k1_ecmult_pippenger_batch; + } else { + max_points = secp256k1_strauss_max_points(scratch); + if (max_points == 0) { + return 0; + } + n_batches = (n+max_points-1)/max_points; + n_batch_points = (n+n_batches-1)/n_batches; + f = secp256k1_ecmult_strauss_batch; + } + for(i = 0; i < n_batches; i++) { + size_t nbp = n < n_batch_points ? n : n_batch_points; + size_t offset = n_batch_points*i; + secp256k1_gej tmp; + if (!f(ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { + return 0; + } + secp256k1_gej_add_var(r, r, &tmp, NULL); + n -= nbp; + } + return 1; +} + +#endif /* SECP256K1_ECMULT_IMPL_H */ diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h index 4daefc43..bb6692ad 100644 --- a/src/secp256k1/src/field.h +++ b/src/secp256k1/src/field.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_ -#define _SECP256K1_FIELD_ +#ifndef SECP256K1_FIELD_H +#define SECP256K1_FIELD_H /** Field element module. * @@ -30,6 +30,8 @@ #error "Please select field implementation" #endif +#include "util.h" + /** Normalize a field element. */ static void secp256k1_fe_normalize(secp256k1_fe *r); @@ -50,6 +52,9 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); /** Set a field element equal to a small integer. Resulting field element is normalized. */ static void secp256k1_fe_set_int(secp256k1_fe *r, int a); +/** Sets a field element equal to zero, initializing all fields. */ +static void secp256k1_fe_clear(secp256k1_fe *a); + /** Verify whether a field element is zero. Requires the input to be normalized. */ static int secp256k1_fe_is_zero(const secp256k1_fe *a); @@ -124,4 +129,4 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); -#endif +#endif /* SECP256K1_FIELD_H */ diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h index 61ee1e09..727c5267 100644 --- a/src/secp256k1/src/field_10x26.h +++ b/src/secp256k1/src/field_10x26.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ +#ifndef SECP256K1_FIELD_REPR_H +#define SECP256K1_FIELD_REPR_H #include @@ -44,4 +44,5 @@ typedef struct { #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] -#endif + +#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h index 7b8c0796..94f8132f 100644 --- a/src/secp256k1/src/field_10x26_impl.h +++ b/src/secp256k1/src/field_10x26_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ +#ifndef SECP256K1_FIELD_REPR_IMPL_H +#define SECP256K1_FIELD_REPR_IMPL_H #include "util.h" #include "num.h" @@ -38,10 +38,6 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -325,17 +321,17 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; - } - } + r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); + r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); + r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); + r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18); + r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24); + r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22); + r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20); + r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18); + r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); + r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); + if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { return 0; } @@ -349,21 +345,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); - } - r[31-i] = c; - } + r[0] = (a->n[9] >> 14) & 0xff; + r[1] = (a->n[9] >> 6) & 0xff; + r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); + r[3] = (a->n[8] >> 16) & 0xff; + r[4] = (a->n[8] >> 8) & 0xff; + r[5] = a->n[8] & 0xff; + r[6] = (a->n[7] >> 18) & 0xff; + r[7] = (a->n[7] >> 10) & 0xff; + r[8] = (a->n[7] >> 2) & 0xff; + r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f); + r[10] = (a->n[6] >> 12) & 0xff; + r[11] = (a->n[6] >> 4) & 0xff; + r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf); + r[13] = (a->n[5] >> 14) & 0xff; + r[14] = (a->n[5] >> 6) & 0xff; + r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3); + r[16] = (a->n[4] >> 16) & 0xff; + r[17] = (a->n[4] >> 8) & 0xff; + r[18] = a->n[4] & 0xff; + r[19] = (a->n[3] >> 18) & 0xff; + r[20] = (a->n[3] >> 10) & 0xff; + r[21] = (a->n[3] >> 2) & 0xff; + r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f); + r[23] = (a->n[2] >> 12) & 0xff; + r[24] = (a->n[2] >> 4) & 0xff; + r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf); + r[26] = (a->n[1] >> 14) & 0xff; + r[27] = (a->n[1] >> 6) & 0xff; + r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3); + r[29] = (a->n[0] >> 16) & 0xff; + r[30] = (a->n[0] >> 8) & 0xff; + r[31] = a->n[0] & 0xff; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { @@ -1141,4 +1158,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif +#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h index 8e69a560..bccd8feb 100644 --- a/src/secp256k1/src/field_5x52.h +++ b/src/secp256k1/src/field_5x52.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ +#ifndef SECP256K1_FIELD_REPR_H +#define SECP256K1_FIELD_REPR_H #include @@ -44,4 +44,4 @@ typedef struct { (d6) | (((uint64_t)(d7)) << 32) \ }} -#endif +#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h index 98cc004b..1fc3171f 100644 --- a/src/secp256k1/src/field_5x52_asm_impl.h +++ b/src/secp256k1/src/field_5x52_asm_impl.h @@ -11,8 +11,8 @@ * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly */ -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H +#define SECP256K1_FIELD_INNER5X52_IMPL_H SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { /** @@ -499,4 +499,4 @@ __asm__ __volatile__( ); } -#endif +#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h index 7a99eb21..957c61b0 100644 --- a/src/secp256k1/src/field_5x52_impl.h +++ b/src/secp256k1/src/field_5x52_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ +#ifndef SECP256K1_FIELD_REPR_IMPL_H +#define SECP256K1_FIELD_REPR_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -49,10 +49,6 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -288,16 +284,40 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; - } - } + r->n[0] = (uint64_t)a[31] + | ((uint64_t)a[30] << 8) + | ((uint64_t)a[29] << 16) + | ((uint64_t)a[28] << 24) + | ((uint64_t)a[27] << 32) + | ((uint64_t)a[26] << 40) + | ((uint64_t)(a[25] & 0xF) << 48); + r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) + | ((uint64_t)a[24] << 4) + | ((uint64_t)a[23] << 12) + | ((uint64_t)a[22] << 20) + | ((uint64_t)a[21] << 28) + | ((uint64_t)a[20] << 36) + | ((uint64_t)a[19] << 44); + r->n[2] = (uint64_t)a[18] + | ((uint64_t)a[17] << 8) + | ((uint64_t)a[16] << 16) + | ((uint64_t)a[15] << 24) + | ((uint64_t)a[14] << 32) + | ((uint64_t)a[13] << 40) + | ((uint64_t)(a[12] & 0xF) << 48); + r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) + | ((uint64_t)a[11] << 4) + | ((uint64_t)a[10] << 12) + | ((uint64_t)a[9] << 20) + | ((uint64_t)a[8] << 28) + | ((uint64_t)a[7] << 36) + | ((uint64_t)a[6] << 44); + r->n[4] = (uint64_t)a[5] + | ((uint64_t)a[4] << 8) + | ((uint64_t)a[3] << 16) + | ((uint64_t)a[2] << 24) + | ((uint64_t)a[1] << 32) + | ((uint64_t)a[0] << 40); if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { return 0; } @@ -311,21 +331,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); - } - r[31-i] = c; - } + r[0] = (a->n[4] >> 40) & 0xFF; + r[1] = (a->n[4] >> 32) & 0xFF; + r[2] = (a->n[4] >> 24) & 0xFF; + r[3] = (a->n[4] >> 16) & 0xFF; + r[4] = (a->n[4] >> 8) & 0xFF; + r[5] = a->n[4] & 0xFF; + r[6] = (a->n[3] >> 44) & 0xFF; + r[7] = (a->n[3] >> 36) & 0xFF; + r[8] = (a->n[3] >> 28) & 0xFF; + r[9] = (a->n[3] >> 20) & 0xFF; + r[10] = (a->n[3] >> 12) & 0xFF; + r[11] = (a->n[3] >> 4) & 0xFF; + r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); + r[13] = (a->n[2] >> 40) & 0xFF; + r[14] = (a->n[2] >> 32) & 0xFF; + r[15] = (a->n[2] >> 24) & 0xFF; + r[16] = (a->n[2] >> 16) & 0xFF; + r[17] = (a->n[2] >> 8) & 0xFF; + r[18] = a->n[2] & 0xFF; + r[19] = (a->n[1] >> 44) & 0xFF; + r[20] = (a->n[1] >> 36) & 0xFF; + r[21] = (a->n[1] >> 28) & 0xFF; + r[22] = (a->n[1] >> 20) & 0xFF; + r[23] = (a->n[1] >> 12) & 0xFF; + r[24] = (a->n[1] >> 4) & 0xFF; + r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); + r[26] = (a->n[0] >> 40) & 0xFF; + r[27] = (a->n[0] >> 32) & 0xFF; + r[28] = (a->n[0] >> 24) & 0xFF; + r[29] = (a->n[0] >> 16) & 0xFF; + r[30] = (a->n[0] >> 8) & 0xFF; + r[31] = a->n[0] & 0xFF; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { @@ -452,4 +493,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif +#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h index 0bf22bdd..95a0d179 100644 --- a/src/secp256k1/src/field_5x52_int128_impl.h +++ b/src/secp256k1/src/field_5x52_int128_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H +#define SECP256K1_FIELD_INNER5X52_IMPL_H #include @@ -274,4 +274,4 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -#endif +#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h index 5127b279..20428648 100644 --- a/src/secp256k1/src/field_impl.h +++ b/src/secp256k1/src/field_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_IMPL_H_ -#define _SECP256K1_FIELD_IMPL_H_ +#ifndef SECP256K1_FIELD_IMPL_H +#define SECP256K1_FIELD_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -312,4 +312,4 @@ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { #endif } -#endif +#endif /* SECP256K1_FIELD_IMPL_H */ diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c index 1835fd49..87d296eb 100644 --- a/src/secp256k1/src/gen_context.c +++ b/src/secp256k1/src/gen_context.c @@ -41,7 +41,7 @@ int main(int argc, char **argv) { fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#include \"group.h\"\n"); + fprintf(fp, "#include \"src/group.h\"\n"); fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index 4957b248..3947ea2d 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_GROUP_ -#define _SECP256K1_GROUP_ +#ifndef SECP256K1_GROUP_H +#define SECP256K1_GROUP_H #include "num.h" #include "field.h" @@ -79,6 +79,9 @@ static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej * stored in globalz. */ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); +/** Set a group element (affine) equal to the point at infinity. */ +static void secp256k1_ge_set_infinity(secp256k1_ge *r); + /** Set a group element (jacobian) equal to the point at infinity. */ static void secp256k1_gej_set_infinity(secp256k1_gej *r); @@ -141,4 +144,4 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); -#endif +#endif /* SECP256K1_GROUP_H */ diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index 18f2b373..b1ace87b 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -4,13 +4,60 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_GROUP_IMPL_H_ -#define _SECP256K1_GROUP_IMPL_H_ +#ifndef SECP256K1_GROUP_IMPL_H +#define SECP256K1_GROUP_IMPL_H #include "num.h" #include "field.h" #include "group.h" +/* These points can be generated in sage as follows: + * + * 0. Setup a worksheet with the following parameters. + * b = 4 # whatever CURVE_B will be set to + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (b)]) + * + * 1. Determine all the small orders available to you. (If there are + * no satisfactory ones, go back and change b.) + * print C.order().factor(limit=1000) + * + * 2. Choose an order as one of the prime factors listed in the above step. + * (You can also multiply some to get a composite order, though the + * tests will crash trying to invert scalars during signing.) We take a + * random point and scale it to drop its order to the desired value. + * There is some probability this won't work; just try again. + * order = 199 + * P = C.random_point() + * P = (int(P.order()) / int(order)) * P + * assert(P.order() == order) + * + * 3. Print the values. You'll need to use a vim macro or something to + * split the hex output into 4-byte chunks. + * print "%x %x" % P.xy() + */ +#if defined(EXHAUSTIVE_TEST_ORDER) +# if EXHAUSTIVE_TEST_ORDER == 199 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, + 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, + 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, + 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED +); + +const int CURVE_B = 4; +# elif EXHAUSTIVE_TEST_ORDER == 13 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, + 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, + 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, + 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac +); +const int CURVE_B = 2; +# else +# error No known generator for the specified exhaustive test group order. +# endif +#else /** Generator for secp256k1, value 'g' defined in * "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ @@ -21,6 +68,9 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL ); +const int CURVE_B = 7; +#endif + static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; @@ -145,9 +195,15 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp static void secp256k1_gej_set_infinity(secp256k1_gej *r) { r->infinity = 1; - secp256k1_fe_set_int(&r->x, 0); - secp256k1_fe_set_int(&r->y, 0); - secp256k1_fe_set_int(&r->z, 0); + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_ge_set_infinity(secp256k1_ge *r) { + r->infinity = 1; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); } static void secp256k1_gej_clear(secp256k1_gej *r) { @@ -169,7 +225,7 @@ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; - secp256k1_fe_set_int(&c, 7); + secp256k1_fe_set_int(&c, CURVE_B); secp256k1_fe_add(&c, &x3); return secp256k1_fe_sqrt(&r->y, &c); } @@ -228,7 +284,7 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); - secp256k1_fe_mul_int(&z6, 7); + secp256k1_fe_mul_int(&z6, CURVE_B); secp256k1_fe_add(&x3, &z6); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); @@ -242,7 +298,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { /* y^2 = x^3 + 7 */ secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_set_int(&c, 7); + secp256k1_fe_set_int(&c, CURVE_B); secp256k1_fe_add(&x3, &c); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); @@ -647,4 +703,4 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { return secp256k1_fe_is_quad_var(&yz); } -#endif +#endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h index fca98cab..de26e4b8 100644 --- a/src/secp256k1/src/hash.h +++ b/src/secp256k1/src/hash.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_HASH_ -#define _SECP256K1_HASH_ +#ifndef SECP256K1_HASH_H +#define SECP256K1_HASH_H #include #include @@ -14,28 +14,28 @@ typedef struct { uint32_t s[8]; uint32_t buf[16]; /* In big endian */ size_t bytes; -} secp256k1_sha256_t; +} secp256k1_sha256; -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); +static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); +static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); typedef struct { - secp256k1_sha256_t inner, outer; -} secp256k1_hmac_sha256_t; + secp256k1_sha256 inner, outer; +} secp256k1_hmac_sha256; -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); typedef struct { unsigned char v[32]; unsigned char k[32]; int retry; -} secp256k1_rfc6979_hmac_sha256_t; +} secp256k1_rfc6979_hmac_sha256; -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); -#endif +#endif /* SECP256K1_HASH_H */ diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h index b47e65f8..009f26be 100644 --- a/src/secp256k1/src/hash_impl.h +++ b/src/secp256k1/src/hash_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_HASH_IMPL_H_ -#define _SECP256K1_HASH_IMPL_H_ +#ifndef SECP256K1_HASH_IMPL_H +#define SECP256K1_HASH_IMPL_H #include "hash.h" @@ -33,7 +33,7 @@ #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #endif -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { +static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; @@ -128,14 +128,15 @@ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { s[7] += h; } -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { +static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; while (bufsize + len >= 64) { /* Fill the buffer, and process it. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); - data += 64 - bufsize; - len -= 64 - bufsize; + size_t chunk_len = 64 - bufsize; + memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); + data += chunk_len; + len -= chunk_len; secp256k1_sha256_transform(hash->s, hash->buf); bufsize = 0; } @@ -145,7 +146,7 @@ static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char } } -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { +static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t sizedesc[2]; uint32_t out[8]; @@ -161,14 +162,14 @@ static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *o memcpy(out32, (const unsigned char*)out, 32); } -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { - int n; +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { + size_t n; unsigned char rkey[64]; - if (keylen <= 64) { + if (keylen <= sizeof(rkey)) { memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, 64 - keylen); + memset(rkey + keylen, 0, sizeof(rkey) - keylen); } else { - secp256k1_sha256_t sha256; + secp256k1_sha256 sha256; secp256k1_sha256_initialize(&sha256); secp256k1_sha256_write(&sha256, key, keylen); secp256k1_sha256_finalize(&sha256, rkey); @@ -176,24 +177,24 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, cons } secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < 64; n++) { + for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } - secp256k1_sha256_write(&hash->outer, rkey, 64); + secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < 64; n++) { + for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } - secp256k1_sha256_write(&hash->inner, rkey, 64); - memset(rkey, 0, 64); + secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); + memset(rkey, 0, sizeof(rkey)); } -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { secp256k1_sha256_write(&hash->inner, data, size); } -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { unsigned char temp[32]; secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_write(&hash->outer, temp, 32); @@ -202,8 +203,8 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256_t hmac; +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { + secp256k1_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -232,11 +233,11 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 rng->retry = 0; } -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { - secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256 hmac; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); @@ -247,7 +248,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 } while (outlen > 0) { - secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256 hmac; int now = outlen; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); @@ -263,7 +264,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 rng->retry = 1; } -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { memset(rng->k, 0, 32); memset(rng->v, 0, 32); rng->retry = 0; @@ -278,4 +279,4 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 #undef Maj #undef Ch -#endif +#endif /* SECP256K1_HASH_IMPL_H */ diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java index be67048f..1c67802f 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -32,7 +32,7 @@ *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

* *

To build secp256k1 for use with bitcoinj, run - * `./configure --enable-jni --enable-experimental --enable-module-schnorr --enable-module-ecdh` + * `./configure --enable-jni --enable-experimental --enable-module-ecdh` * and `make` then copy `.libs/libsecp256k1.so` to your system library path * or point the JVM to the folder containing it with -Djava.library.path *

@@ -417,36 +417,6 @@ public static synchronized boolean randomize(byte[] seed) throws AssertFailExcep } } - public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException { - Preconditions.checkArgument(data.length == 32 && sec.length <= 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null) { - byteBuff = ByteBuffer.allocateDirect(32 + 32); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.put(sec); - - byte[][] retByteArray; - - r.lock(); - try { - retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] sigArr = retByteArray[0]; - int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - - assertEquals(sigArr.length, 64, "Got bad signature length."); - - return retVal == 0 ? new byte[0] : sigArr; - } - private static native long secp256k1_ctx_clone(long context); private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); @@ -471,8 +441,6 @@ public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailExcep private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); - private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); - private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); } diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java index f18ce958..c00d0889 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -167,22 +167,6 @@ public static void testRandomize() throws AssertFailException { assertEquals( result, true, "testRandomize"); } - /** - * This tests signSchnorr() for a valid secretkey - */ - public static void testSchnorrSign() throws AssertFailException{ - - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString, "C5E929AA058B982048760422D3B563749B7D0E50C5EBD8CD2FFC23214BD6A2F1B072C13880997EBA847CF20F2F90FCE07C1CA33A890A4127095A351127F8D95F" , "testSchnorrSign"); - } - - /** - * This tests signSchnorr() for a valid secretkey - */ public static void testCreateECDHSecret() throws AssertFailException{ byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); @@ -216,11 +200,6 @@ public static void main(String[] args) throws AssertFailException{ testSignPos(); testSignNeg(); - //Test Schnorr (partial support) //TODO - testSchnorrSign(); - //testSchnorrVerify - //testSchnorrRecovery - //Test privKeyTweakAdd() 1 testPrivKeyTweakAdd_1(); diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c index dba9524d..bcef7b32 100644 --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -5,7 +5,6 @@ #include "include/secp256k1.h" #include "include/secp256k1_ecdh.h" #include "include/secp256k1_recovery.h" -#include "include/secp256k1_schnorr.h" SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone @@ -333,39 +332,6 @@ SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1p return 0; } -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - unsigned char* secKey = (unsigned char*) (data + 32); - - jobjectArray retArray; - jbyteArray sigArray, intsByteArray; - unsigned char intsarray[1]; - unsigned char sig[64]; - - int ret = secp256k1_schnorr_sign(ctx, sig, data, secKey, NULL, NULL); - - intsarray[0] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - sigArray = (*env)->NewByteArray(env, 64); - (*env)->SetByteArrayRegion(env, sigArray, 0, 64, (jbyte*)sig); - (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); - - intsByteArray = (*env)->NewByteArray(env, 1); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) { diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h index 4125a1f5..fe613c9e 100644 --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -104,14 +104,6 @@ SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1e SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse (JNIEnv *, jclass, jobject, jlong, jint); -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_schnorr_sign - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l); - /* * Class: org_bitcoin_NativeSecp256k1 * Method: secp256k1_ecdh diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h index c23e4f82..bd8739ee 100644 --- a/src/secp256k1/src/modules/ecdh/main_impl.h +++ b/src/secp256k1/src/modules/ecdh/main_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_MODULE_ECDH_MAIN_ -#define _SECP256K1_MODULE_ECDH_MAIN_ +#ifndef SECP256K1_MODULE_ECDH_MAIN_H +#define SECP256K1_MODULE_ECDH_MAIN_H #include "include/secp256k1_ecdh.h" #include "ecmult_const_impl.h" @@ -16,10 +16,10 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se secp256k1_gej res; secp256k1_ge pt; secp256k1_scalar s; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(result != NULL); ARG_CHECK(point != NULL); ARG_CHECK(scalar != NULL); - (void)ctx; secp256k1_pubkey_load(ctx, &pt, point); secp256k1_scalar_set_b32(&s, scalar, &overflow); @@ -28,7 +28,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se } else { unsigned char x[32]; unsigned char y[1]; - secp256k1_sha256_t sha; + secp256k1_sha256 sha; secp256k1_ecmult_const(&res, &pt, &s); secp256k1_ge_set_gej(&pt, &res); @@ -51,4 +51,4 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se return ret; } -#endif +#endif /* SECP256K1_MODULE_ECDH_MAIN_H */ diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h index 7badc903..0c53f8ee 100644 --- a/src/secp256k1/src/modules/ecdh/tests_impl.h +++ b/src/secp256k1/src/modules/ecdh/tests_impl.h @@ -4,8 +4,37 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_MODULE_ECDH_TESTS_ -#define _SECP256K1_MODULE_ECDH_TESTS_ +#ifndef SECP256K1_MODULE_ECDH_TESTS_H +#define SECP256K1_MODULE_ECDH_TESTS_H + +void test_ecdh_api(void) { + /* Setup context that just counts errors */ + secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_pubkey point; + unsigned char res[32]; + unsigned char s_one[32] = { 0 }; + int32_t ecount = 0; + s_one[31] = 1; + + secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); + + /* Check all NULLs are detected */ + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 3); + + /* Cleanup */ + secp256k1_context_destroy(tctx); +} void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; @@ -15,7 +44,7 @@ void test_ecdh_generator_basepoint(void) { s_one[31] = 1; /* Check against pubkey creation when the basepoint is the generator */ for (i = 0; i < 100; ++i) { - secp256k1_sha256_t sha; + secp256k1_sha256 sha; unsigned char s_b32[32]; unsigned char output_ecdh[32]; unsigned char output_ser[32]; @@ -68,8 +97,9 @@ void test_bad_scalar(void) { } void run_ecdh_tests(void) { + test_ecdh_api(); test_ecdh_generator_basepoint(); test_bad_scalar(); } -#endif +#endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/src/secp256k1/src/modules/recovery/main_impl.h b/src/secp256k1/src/modules/recovery/main_impl.h index 86f2f0cb..2f6691c5 100644 --- a/src/secp256k1/src/modules/recovery/main_impl.h +++ b/src/secp256k1/src/modules/recovery/main_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ -#define _SECP256K1_MODULE_RECOVERY_MAIN_ +#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H +#define SECP256K1_MODULE_RECOVERY_MAIN_H #include "include/secp256k1_recovery.h" @@ -179,7 +179,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk ARG_CHECK(pubkey != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - ARG_CHECK(recid >= 0 && recid < 4); + VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ secp256k1_scalar_set_b32(&m, msg32, NULL); if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { secp256k1_pubkey_save(pubkey, &q); @@ -190,4 +190,4 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk } } -#endif +#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */ diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h index 8932d5f0..5c9bbe86 100644 --- a/src/secp256k1/src/modules/recovery/tests_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_impl.h @@ -4,8 +4,148 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ -#define _SECP256K1_MODULE_RECOVERY_TESTS_ +#ifndef SECP256K1_MODULE_RECOVERY_TESTS_H +#define SECP256K1_MODULE_RECOVERY_TESTS_H + +static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void) msg32; + (void) key32; + (void) algo16; + (void) data; + + /* On the first run, return 0 to force a second run */ + if (counter == 0) { + memset(nonce32, 0, 32); + return 1; + } + /* On the second run, return an overflow to force a third run */ + if (counter == 1) { + memset(nonce32, 0xff, 32); + return 1; + } + /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ + memset(nonce32, 1, 32); + return secp256k1_rand_bits(1); +} + +void test_ecdsa_recovery_api(void) { + /* Setup contexts that just count errors */ + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + secp256k1_ecdsa_signature normal_sig; + secp256k1_ecdsa_recoverable_signature recsig; + unsigned char privkey[32] = { 1 }; + unsigned char message[32] = { 2 }; + int32_t ecount = 0; + int recid = 0; + unsigned char sig[74]; + unsigned char zero_privkey[32] = { 0 }; + unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Check bad contexts and NULLs for signing */ + ecount = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); + CHECK(ecount == 5); + /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ + secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); + CHECK(ecount == 5); + /* These will all fail, but not in ARG_CHECK way */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); + /* This one will succeed. */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 5); + + /* Check signing with a goofy nonce function */ + + /* Check bad contexts and NULLs for recovery */ + ecount = 0; + CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); + CHECK(ecount == 5); + + /* Check NULLs for conversion */ + CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); + + /* Check NULLs for de/serialization */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); + CHECK(ecount == 7); + /* overflow in signature will fail but not affect ecount */ + memcpy(sig, over_privkey, 32); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); + CHECK(ecount == 7); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); +} void test_ecdsa_recovery_end_to_end(void) { unsigned char extra[32] = {0x00}; @@ -241,10 +381,13 @@ void test_ecdsa_recovery_edge_cases(void) { void run_recovery_tests(void) { int i; + for (i = 0; i < count; i++) { + test_ecdsa_recovery_api(); + } for (i = 0; i < 64*count; i++) { test_ecdsa_recovery_end_to_end(); } test_ecdsa_recovery_edge_cases(); } -#endif +#endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */ diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h index 7bb9c5be..49f2dd79 100644 --- a/src/secp256k1/src/num.h +++ b/src/secp256k1/src/num.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_ -#define _SECP256K1_NUM_ +#ifndef SECP256K1_NUM_H +#define SECP256K1_NUM_H #ifndef USE_NUM_NONE @@ -71,4 +71,4 @@ static void secp256k1_num_negate(secp256k1_num *r); #endif -#endif +#endif /* SECP256K1_NUM_H */ diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h index 7dd81308..3619844b 100644 --- a/src/secp256k1/src/num_gmp.h +++ b/src/secp256k1/src/num_gmp.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_REPR_ -#define _SECP256K1_NUM_REPR_ +#ifndef SECP256K1_NUM_REPR_H +#define SECP256K1_NUM_REPR_H #include @@ -17,4 +17,4 @@ typedef struct { int limbs; } secp256k1_num; -#endif +#endif /* SECP256K1_NUM_REPR_H */ diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h index 3a46495e..0ae2a8ba 100644 --- a/src/secp256k1/src/num_gmp_impl.h +++ b/src/secp256k1/src/num_gmp_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_REPR_IMPL_H_ -#define _SECP256K1_NUM_REPR_IMPL_H_ +#ifndef SECP256K1_NUM_REPR_IMPL_H +#define SECP256K1_NUM_REPR_IMPL_H #include #include @@ -285,4 +285,4 @@ static void secp256k1_num_negate(secp256k1_num *r) { r->neg ^= 1; } -#endif +#endif /* SECP256K1_NUM_REPR_IMPL_H */ diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h index 0b0e3a07..c45193b0 100644 --- a/src/secp256k1/src/num_impl.h +++ b/src/secp256k1/src/num_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_IMPL_H_ -#define _SECP256K1_NUM_IMPL_H_ +#ifndef SECP256K1_NUM_IMPL_H +#define SECP256K1_NUM_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -21,4 +21,4 @@ #error "Please select num implementation" #endif -#endif +#endif /* SECP256K1_NUM_IMPL_H */ diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h index b590ccd6..59304cb6 100644 --- a/src/secp256k1/src/scalar.h +++ b/src/secp256k1/src/scalar.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_ -#define _SECP256K1_SCALAR_ +#ifndef SECP256K1_SCALAR_H +#define SECP256K1_SCALAR_H #include "num.h" @@ -13,7 +13,9 @@ #include "libsecp256k1-config.h" #endif -#if defined(USE_SCALAR_4X64) +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low.h" +#elif defined(USE_SCALAR_4X64) #include "scalar_4x64.h" #elif defined(USE_SCALAR_8X32) #include "scalar_8x32.h" @@ -101,4 +103,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); -#endif +#endif /* SECP256K1_SCALAR_H */ diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h index cff40603..19c7495d 100644 --- a/src/secp256k1/src/scalar_4x64.h +++ b/src/secp256k1/src/scalar_4x64.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ +#ifndef SECP256K1_SCALAR_REPR_H +#define SECP256K1_SCALAR_REPR_H #include @@ -16,4 +16,4 @@ typedef struct { #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} -#endif +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h index 56e7bd82..db1ebf94 100644 --- a/src/secp256k1/src/scalar_4x64_impl.h +++ b/src/secp256k1/src/scalar_4x64_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) @@ -946,4 +946,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); } -#endif +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h index 1319664f..2c9a348e 100644 --- a/src/secp256k1/src/scalar_8x32.h +++ b/src/secp256k1/src/scalar_8x32.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ +#ifndef SECP256K1_SCALAR_REPR_H +#define SECP256K1_SCALAR_REPR_H #include @@ -16,4 +16,4 @@ typedef struct { #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} -#endif +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h index aae4f35c..4f9ed61f 100644 --- a/src/secp256k1/src/scalar_8x32_impl.h +++ b/src/secp256k1/src/scalar_8x32_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint32_t)0xD0364141UL) @@ -718,4 +718,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); } -#endif +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index c5baf4df..fa790570 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_IMPL_H_ -#define _SECP256K1_SCALAR_IMPL_H_ +#ifndef SECP256K1_SCALAR_IMPL_H +#define SECP256K1_SCALAR_IMPL_H #include "group.h" #include "scalar.h" @@ -14,7 +14,9 @@ #include "libsecp256k1-config.h" #endif -#if defined(USE_SCALAR_4X64) +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low_impl.h" +#elif defined(USE_SCALAR_4X64) #include "scalar_4x64_impl.h" #elif defined(USE_SCALAR_8X32) #include "scalar_8x32_impl.h" @@ -31,101 +33,112 @@ static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a /** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ static void secp256k1_scalar_order_get_num(secp256k1_num *r) { +#if defined(EXHAUSTIVE_TEST_ORDER) + static const unsigned char order[32] = { + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER + }; +#else static const unsigned char order[32] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 }; +#endif secp256k1_num_set_bin(r, order, 32); } #endif static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { +#if defined(EXHAUSTIVE_TEST_ORDER) + int i; + *r = 0; + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) + if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) + *r = i; + /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus + * have a composite group order; fix it in exhaustive_tests.c). */ + VERIFY_CHECK(*r != 0); +} +#else secp256k1_scalar *t; int i; - /* First compute x ^ (2^N - 1) for some values of N. */ - secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; - - secp256k1_scalar_sqr(&x2, x); - secp256k1_scalar_mul(&x2, &x2, x); + /* First compute xN as x ^ (2^N - 1) for some values of N, + * and uM as x ^ M for some values of M. */ + secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126; + secp256k1_scalar u2, u5, u9, u11, u13; - secp256k1_scalar_sqr(&x3, &x2); - secp256k1_scalar_mul(&x3, &x3, x); + secp256k1_scalar_sqr(&u2, x); + secp256k1_scalar_mul(&x2, &u2, x); + secp256k1_scalar_mul(&u5, &u2, &x2); + secp256k1_scalar_mul(&x3, &u5, &u2); + secp256k1_scalar_mul(&u9, &x3, &u2); + secp256k1_scalar_mul(&u11, &u9, &u2); + secp256k1_scalar_mul(&u13, &u11, &u2); - secp256k1_scalar_sqr(&x4, &x3); - secp256k1_scalar_mul(&x4, &x4, x); - - secp256k1_scalar_sqr(&x6, &x4); + secp256k1_scalar_sqr(&x6, &u13); secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &x2); - - secp256k1_scalar_sqr(&x7, &x6); - secp256k1_scalar_mul(&x7, &x7, x); + secp256k1_scalar_mul(&x6, &x6, &u11); - secp256k1_scalar_sqr(&x8, &x7); - secp256k1_scalar_mul(&x8, &x8, x); + secp256k1_scalar_sqr(&x8, &x6); + secp256k1_scalar_sqr(&x8, &x8); + secp256k1_scalar_mul(&x8, &x8, &x2); - secp256k1_scalar_sqr(&x15, &x8); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x15, &x15); + secp256k1_scalar_sqr(&x14, &x8); + for (i = 0; i < 5; i++) { + secp256k1_scalar_sqr(&x14, &x14); } - secp256k1_scalar_mul(&x15, &x15, &x7); + secp256k1_scalar_mul(&x14, &x14, &x6); - secp256k1_scalar_sqr(&x30, &x15); - for (i = 0; i < 14; i++) { - secp256k1_scalar_sqr(&x30, &x30); + secp256k1_scalar_sqr(&x28, &x14); + for (i = 0; i < 13; i++) { + secp256k1_scalar_sqr(&x28, &x28); } - secp256k1_scalar_mul(&x30, &x30, &x15); + secp256k1_scalar_mul(&x28, &x28, &x14); - secp256k1_scalar_sqr(&x60, &x30); - for (i = 0; i < 29; i++) { - secp256k1_scalar_sqr(&x60, &x60); + secp256k1_scalar_sqr(&x56, &x28); + for (i = 0; i < 27; i++) { + secp256k1_scalar_sqr(&x56, &x56); } - secp256k1_scalar_mul(&x60, &x60, &x30); + secp256k1_scalar_mul(&x56, &x56, &x28); - secp256k1_scalar_sqr(&x120, &x60); - for (i = 0; i < 59; i++) { - secp256k1_scalar_sqr(&x120, &x120); + secp256k1_scalar_sqr(&x112, &x56); + for (i = 0; i < 55; i++) { + secp256k1_scalar_sqr(&x112, &x112); } - secp256k1_scalar_mul(&x120, &x120, &x60); + secp256k1_scalar_mul(&x112, &x112, &x56); - secp256k1_scalar_sqr(&x127, &x120); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x127, &x127); + secp256k1_scalar_sqr(&x126, &x112); + for (i = 0; i < 13; i++) { + secp256k1_scalar_sqr(&x126, &x126); } - secp256k1_scalar_mul(&x127, &x127, &x7); + secp256k1_scalar_mul(&x126, &x126, &x14); - /* Then accumulate the final result (t starts at x127). */ - t = &x127; - for (i = 0; i < 2; i++) { /* 0 */ + /* Then accumulate the final result (t starts at x126). */ + t = &x126; + for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ + for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } @@ -134,38 +147,26 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 00 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 10; i++) { /* 0000000 */ secp256k1_scalar_sqr(t, t); } @@ -178,50 +179,34 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 000 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 5; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 000000 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 10; i++) { /* 000000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ for (i = 0; i < 6; i++) { /* 00000 */ secp256k1_scalar_sqr(t, t); } @@ -233,9 +218,9 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar } SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - /* d[0] is present and is the lowest word for all representations */ return !(a->d[0] & 1); } +#endif static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { #if defined(USE_SCALAR_INV_BUILTIN) @@ -259,6 +244,18 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_sc } #ifdef USE_ENDOMORPHISM +#if defined(EXHAUSTIVE_TEST_ORDER) +/** + * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the + * full case we don't bother making k1 and k2 be small, we just want them to be + * nontrivial to get full test coverage for the exhaustive tests. We therefore + * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. + */ +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; + *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; +} +#else /** * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, @@ -331,5 +328,6 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar secp256k1_scalar_add(r1, r1, a); } #endif - #endif + +#endif /* SECP256K1_SCALAR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_low.h b/src/secp256k1/src/scalar_low.h new file mode 100644 index 00000000..5836febc --- /dev/null +++ b/src/secp256k1/src/scalar_low.h @@ -0,0 +1,15 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_SCALAR_REPR_H +#define SECP256K1_SCALAR_REPR_H + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef uint32_t secp256k1_scalar; + +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_low_impl.h b/src/secp256k1/src/scalar_low_impl.h new file mode 100644 index 00000000..c80e70c5 --- /dev/null +++ b/src/secp256k1/src/scalar_low_impl.h @@ -0,0 +1,114 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H + +#include "scalar.h" + +#include + +SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + return !(*a & 1); +} + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + if (offset < 32) + return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); + else + return 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + return secp256k1_scalar_get_bits(a, offset, count); +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; + return *r < *b; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + if (flag && bit < 32) + *r += (1 << bit); +#ifdef VERIFY + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; + int i; + *r = 0; + for (i = 0; i < 32; i++) { + *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; + } + /* just deny overflow, it basically always happens */ + if (overflow) *overflow = 0; +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + memset(bin, 0, 32); + bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return *a == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + if (*a == 0) { + *r = 0; + } else { + *r = EXHAUSTIVE_TEST_ORDER - *a; + } +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return *a == 1; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + return *a > EXHAUSTIVE_TEST_ORDER / 2; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + if (flag) secp256k1_scalar_negate(r, r); + return flag ? -1 : 1; +} + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = *r & ((1 << n) - 1); + *r >>= n; + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; +} + +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r1 = *a; + *r2 = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return *a == *b; +} + +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h new file mode 100644 index 00000000..aba56e21 --- /dev/null +++ b/src/secp256k1/src/scratch.h @@ -0,0 +1,35 @@ +/********************************************************************** + * Copyright (c) 2017 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCRATCH_ +#define _SECP256K1_SCRATCH_ + +/* The typedef is used internally; the struct name is used in the public API + * (where it is exposed as a different typedef) */ +typedef struct secp256k1_scratch_space_struct { + void *data; + size_t offset; + size_t init_size; + size_t max_size; + const secp256k1_callback* error_callback; +} secp256k1_scratch; + +static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size); +static void secp256k1_scratch_destroy(secp256k1_scratch* scratch); + +/** Returns the maximum allocation the scratch space will allow */ +static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t n_objects); + +/** Attempts to allocate so that there are `n` available bytes. Returns 1 on success, 0 on failure */ +static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t n_objects); + +/** Returns a pointer into the scratch space or NULL if there is insufficient available space */ +static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t n); + +/** Resets the returned pointer to the beginning of space */ +static void secp256k1_scratch_reset(secp256k1_scratch* scratch); + +#endif diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h new file mode 100644 index 00000000..9bd68fe1 --- /dev/null +++ b/src/secp256k1/src/scratch_impl.h @@ -0,0 +1,77 @@ +/********************************************************************** + * Copyright (c) 2017 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCRATCH_IMPL_H_ +#define _SECP256K1_SCRATCH_IMPL_H_ + +#include "scratch.h" + +/* Using 16 bytes alignment because common architectures never have alignment + * requirements above 8 for any of the types we care about. In addition we + * leave some room because currently we don't care about a few bytes. + * TODO: Determine this at configure time. */ +#define ALIGNMENT 16 + +static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size) { + secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret)); + if (ret != NULL) { + ret->data = checked_malloc(error_callback, init_size); + if (ret->data == NULL) { + free (ret); + return NULL; + } + ret->offset = 0; + ret->init_size = init_size; + ret->max_size = max_size; + ret->error_callback = error_callback; + } + return ret; +} + +static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) { + if (scratch != NULL) { + free(scratch->data); + free(scratch); + } +} + +static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) { + if (scratch->max_size <= objects * ALIGNMENT) { + return 0; + } + return scratch->max_size - objects * ALIGNMENT; +} + +static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t objects) { + n += objects * ALIGNMENT; + if (n > scratch->init_size && n <= scratch->max_size) { + void *tmp = checked_realloc(scratch->error_callback, scratch->data, n); + if (tmp == NULL) { + return 0; + } + scratch->init_size = n; + scratch->data = tmp; + } + return n <= scratch->max_size; +} + +static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) { + void *ret; + size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; + if (size + scratch->offset > scratch->init_size) { + return NULL; + } + ret = (void *) ((unsigned char *) scratch->data + scratch->offset); + memset(ret, 0, size); + scratch->offset += size; + return ret; +} + +static void secp256k1_scratch_reset(secp256k1_scratch* scratch) { + scratch->offset = 0; +} + +#endif diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index fb8b882f..7e3ad572 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -17,6 +17,7 @@ #include "ecdsa_impl.h" #include "eckey_impl.h" #include "hash_impl.h" +#include "scratch_impl.h" #define ARG_CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ @@ -114,13 +115,24 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } +secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t init_size, size_t max_size) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(max_size >= init_size); + + return secp256k1_scratch_create(&ctx->error_callback, init_size, max_size); +} + +void secp256k1_scratch_space_destroy(secp256k1_scratch_space* scratch) { + secp256k1_scratch_destroy(scratch); +} + static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { if (sizeof(secp256k1_ge_storage) == 64) { /* When the secp256k1_ge_storage type is exactly 64 byte, use its * representation inside secp256k1_pubkey, as conversion is very fast. * Note that secp256k1_pubkey_save must use the same representation. */ secp256k1_ge_storage s; - memcpy(&s, &pubkey->data[0], 64); + memcpy(&s, &pubkey->data[0], sizeof(s)); secp256k1_ge_from_storage(ge, &s); } else { /* Otherwise, fall back to 32-byte big endian for X and Y. */ @@ -137,7 +149,7 @@ static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { if (sizeof(secp256k1_ge_storage) == 64) { secp256k1_ge_storage s; secp256k1_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, 64); + memcpy(&pubkey->data[0], &s, sizeof(s)); } else { VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); secp256k1_fe_normalize_var(&ge->x); @@ -307,10 +319,15 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); } +static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { + memcpy(buf + *offset, data, len); + *offset += len; +} + static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { unsigned char keydata[112]; - int keylen = 64; - secp256k1_rfc6979_hmac_sha256_t rng; + unsigned int offset = 0; + secp256k1_rfc6979_hmac_sha256 rng; unsigned int i; /* We feed a byte array to the PRNG as input, consisting of: * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. @@ -320,17 +337,15 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m * different argument mixtures to emulate each other and result in the same * nonces. */ - memcpy(keydata, key32, 32); - memcpy(keydata + 32, msg32, 32); + buffer_append(keydata, &offset, key32, 32); + buffer_append(keydata, &offset, msg32, 32); if (data != NULL) { - memcpy(keydata + 64, data, 32); - keylen = 96; + buffer_append(keydata, &offset, data, 32); } if (algo16 != NULL) { - memcpy(keydata + keylen, algo16, 16); - keylen += 16; + buffer_append(keydata, &offset, algo16, 16); } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); memset(keydata, 0, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); @@ -424,6 +439,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p return ret; } +int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { + secp256k1_scalar sec; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, NULL); + secp256k1_scalar_negate(&sec, &sec); + secp256k1_scalar_get_b32(seckey, &sec); + + return 1; +} + +int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { + int ret = 0; + secp256k1_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + + ret = secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + secp256k1_ge_neg(&p, &p); + secp256k1_pubkey_save(pubkey, &p); + } + return ret; +} + int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { secp256k1_scalar term; secp256k1_scalar sec; @@ -552,10 +594,6 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey * # include "modules/ecdh/main_impl.h" #endif -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/main_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/main_impl.h" #endif diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h index f8efa93c..f1f9be07 100644 --- a/src/secp256k1/src/testrand.h +++ b/src/secp256k1/src/testrand.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_TESTRAND_H_ -#define _SECP256K1_TESTRAND_H_ +#ifndef SECP256K1_TESTRAND_H +#define SECP256K1_TESTRAND_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -35,4 +35,4 @@ static void secp256k1_rand256_test(unsigned char *b32); /** Generate pseudorandom bytes with long sequences of zero and one bits. */ static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); -#endif +#endif /* SECP256K1_TESTRAND_H */ diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h index 15c7b9f1..30a91e52 100644 --- a/src/secp256k1/src/testrand_impl.h +++ b/src/secp256k1/src/testrand_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_TESTRAND_IMPL_H_ -#define _SECP256K1_TESTRAND_IMPL_H_ +#ifndef SECP256K1_TESTRAND_IMPL_H +#define SECP256K1_TESTRAND_IMPL_H #include #include @@ -13,7 +13,7 @@ #include "testrand.h" #include "hash.h" -static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; +static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng; static uint32_t secp256k1_test_rng_precomputed[8]; static int secp256k1_test_rng_precomputed_used = 8; static uint64_t secp256k1_test_rng_integer; @@ -107,4 +107,4 @@ static void secp256k1_rand256_test(unsigned char *b32) { secp256k1_rand_bytes_test(b32, 32); } -#endif +#endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 15982da8..893d2972 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -10,6 +10,7 @@ #include #include +#include #include @@ -23,7 +24,7 @@ #include "openssl/ecdsa.h" #include "openssl/obj_mac.h" # if OPENSSL_VERSION_NUMBER < 0x10100000L -# define ECDSA_SIG_get0(sig, _r, _s) *(_r) = sig->r; *(_s) = sig->s +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {*pr = sig->r; *ps = sig->s;} # endif #endif @@ -138,6 +139,7 @@ void random_scalar_order(secp256k1_scalar *num) { void run_context_tests(void) { secp256k1_pubkey pubkey; + secp256k1_pubkey zero_pubkey; secp256k1_ecdsa_signature sig; unsigned char ctmp[32]; int32_t ecount; @@ -152,6 +154,8 @@ void run_context_tests(void) { secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; + memset(&zero_pubkey, 0, sizeof(zero_pubkey)); + ecount = 0; ecount2 = 10; secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); @@ -204,12 +208,20 @@ void run_context_tests(void) { CHECK(ecount == 2); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1); CHECK(ecount == 2); - CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0); + CHECK(ecount2 == 14); + CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); CHECK(ecount == 3); + CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(ecount == 4); CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 13); + CHECK(ecount2 == 14); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, NULL); @@ -239,6 +251,41 @@ void run_context_tests(void) { secp256k1_context_destroy(NULL); } +void run_scratch_tests(void) { + int32_t ecount = 0; + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_scratch_space *scratch; + + /* Test public API */ + secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + scratch = secp256k1_scratch_space_create(none, 100, 10); + CHECK(scratch == NULL); + CHECK(ecount == 1); + + scratch = secp256k1_scratch_space_create(none, 100, 100); + CHECK(scratch != NULL); + CHECK(ecount == 1); + secp256k1_scratch_space_destroy(scratch); + + scratch = secp256k1_scratch_space_create(none, 100, 1000); + CHECK(scratch != NULL); + CHECK(ecount == 1); + + /* Test internal API */ + CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); + CHECK(secp256k1_scratch_max_allocation(scratch, 1) < 1000); + CHECK(secp256k1_scratch_resize(scratch, 50, 1) == 1); /* no-op */ + CHECK(secp256k1_scratch_resize(scratch, 200, 1) == 1); + CHECK(secp256k1_scratch_resize(scratch, 950, 1) == 1); + CHECK(secp256k1_scratch_resize(scratch, 1000, 1) == 0); + CHECK(secp256k1_scratch_resize(scratch, 2000, 1) == 0); + CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); + + /* cleanup */ + secp256k1_scratch_space_destroy(scratch); + secp256k1_context_destroy(none); +} + /***** HASH TESTS *****/ void run_sha256_tests(void) { @@ -261,7 +308,7 @@ void run_sha256_tests(void) { int i; for (i = 0; i < 8; i++) { unsigned char out[32]; - secp256k1_sha256_t hasher; + secp256k1_sha256 hasher; secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_sha256_finalize(&hasher, out); @@ -304,7 +351,7 @@ void run_hmac_sha256_tests(void) { }; int i; for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256_t hasher; + secp256k1_hmac_sha256 hasher; unsigned char out[32]; secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); @@ -336,7 +383,7 @@ void run_rfc6979_hmac_sha256_tests(void) { {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} }; - secp256k1_rfc6979_hmac_sha256_t rng; + secp256k1_rfc6979_hmac_sha256 rng; unsigned char out[32]; int i; @@ -1882,9 +1929,9 @@ void test_ge(void) { * * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. */ - secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_fe *zinv = (secp256k1_fe *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe zf; secp256k1_fe zfi2, zfi3; @@ -1922,7 +1969,7 @@ void test_ge(void) { /* Compute z inverses. */ { - secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); for (i = 0; i < 4 * runs + 1; i++) { if (i == 0) { /* The point at infinity does not have a meaningful z inverse. Any should do. */ @@ -2023,7 +2070,7 @@ void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); + secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } @@ -2044,9 +2091,9 @@ void test_ge(void) { /* Test batch gej -> ge conversion with and without known z ratios. */ { - secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_fe *zr = (secp256k1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_fe)); + secp256k1_ge *ge_set_table = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); for (i = 0; i < 4 * runs + 1; i++) { /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ if (i < 4 * runs) { @@ -2478,6 +2525,395 @@ void run_ecmult_const_tests(void) { ecmult_const_chain_multiply(); } +typedef struct { + secp256k1_scalar *sc; + secp256k1_ge *pt; +} ecmult_multi_data; + +static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { + ecmult_multi_data *data = (ecmult_multi_data*) cbdata; + *sc = data->sc[idx]; + *pt = data->pt[idx]; + return 1; +} + +static int ecmult_multi_false_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { + (void)sc; + (void)pt; + (void)idx; + (void)cbdata; + return 0; +} + +void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func ecmult_multi) { + int ncount; + secp256k1_scalar szero; + secp256k1_scalar sc[32]; + secp256k1_ge pt[32]; + secp256k1_gej r; + secp256k1_gej r2; + ecmult_multi_data data; + secp256k1_scratch *scratch_empty; + + data.sc = sc; + data.pt = pt; + secp256k1_scalar_set_int(&szero, 0); + secp256k1_scratch_reset(scratch); + + /* No points to multiply */ + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0)); + + /* Check 1- and 2-point multiplies against ecmult */ + for (ncount = 0; ncount < count; ncount++) { + secp256k1_ge ptg; + secp256k1_gej ptgj; + random_scalar_order(&sc[0]); + random_scalar_order(&sc[1]); + + random_group_element_test(&ptg); + secp256k1_gej_set_ge(&ptgj, &ptg); + pt[0] = ptg; + pt[1] = secp256k1_ge_const_g; + + /* only G scalar */ + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + + /* 1-point */ + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + + /* Try to multiply 1 point, but scratch space is empty */ + scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0, 0); + CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); + secp256k1_scratch_destroy(scratch_empty); + + /* Try to multiply 1 point, but callback returns false */ + CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1)); + + /* 2-point */ + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + + /* 2-point with G scalar */ + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + /* Check infinite outputs of various forms */ + for (ncount = 0; ncount < count; ncount++) { + secp256k1_ge ptg; + size_t i, j; + size_t sizes[] = { 2, 10, 32 }; + + for (j = 0; j < 3; j++) { + for (i = 0; i < 32; i++) { + random_scalar_order(&sc[i]); + secp256k1_ge_set_infinity(&pt[i]); + } + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + for (j = 0; j < 3; j++) { + for (i = 0; i < 32; i++) { + random_group_element_test(&ptg); + pt[i] = ptg; + secp256k1_scalar_set_int(&sc[i], 0); + } + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + for (j = 0; j < 3; j++) { + random_group_element_test(&ptg); + for (i = 0; i < 16; i++) { + random_scalar_order(&sc[2*i]); + secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]); + pt[2 * i] = ptg; + pt[2 * i + 1] = ptg; + } + + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(secp256k1_gej_is_infinity(&r)); + + random_scalar_order(&sc[0]); + for (i = 0; i < 16; i++) { + random_group_element_test(&ptg); + + sc[2*i] = sc[0]; + sc[2*i+1] = sc[0]; + pt[2 * i] = ptg; + secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]); + } + + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + random_group_element_test(&ptg); + secp256k1_scalar_set_int(&sc[0], 0); + pt[0] = ptg; + for (i = 1; i < 32; i++) { + pt[i] = ptg; + + random_scalar_order(&sc[i]); + secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]); + secp256k1_scalar_negate(&sc[i], &sc[i]); + } + + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32)); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + /* Check random points, constant scalar */ + for (ncount = 0; ncount < count; ncount++) { + size_t i; + secp256k1_gej_set_infinity(&r); + + random_scalar_order(&sc[0]); + for (i = 0; i < 20; i++) { + secp256k1_ge ptg; + sc[i] = sc[0]; + random_group_element_test(&ptg); + pt[i] = ptg; + secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); + } + + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + /* Check random scalars, constant point */ + for (ncount = 0; ncount < count; ncount++) { + size_t i; + secp256k1_ge ptg; + secp256k1_gej p0j; + secp256k1_scalar rs; + secp256k1_scalar_set_int(&rs, 0); + + random_group_element_test(&ptg); + for (i = 0; i < 20; i++) { + random_scalar_order(&sc[i]); + pt[i] = ptg; + secp256k1_scalar_add(&rs, &rs, &sc[i]); + } + + secp256k1_gej_set_ge(&p0j, &pt[0]); + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + secp256k1_gej_neg(&r2, &r2); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + } + + /* Sanity check that zero scalars don't cause problems */ + secp256k1_scalar_clear(&sc[0]); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + secp256k1_scalar_clear(&sc[1]); + secp256k1_scalar_clear(&sc[2]); + secp256k1_scalar_clear(&sc[3]); + secp256k1_scalar_clear(&sc[4]); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6)); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5)); + CHECK(secp256k1_gej_is_infinity(&r)); + + /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ + { + const size_t TOP = 8; + size_t s0i, s1i; + size_t t0i, t1i; + secp256k1_ge ptg; + secp256k1_gej ptgj; + + random_group_element_test(&ptg); + secp256k1_gej_set_ge(&ptgj, &ptg); + + for(t0i = 0; t0i < TOP; t0i++) { + for(t1i = 0; t1i < TOP; t1i++) { + secp256k1_gej t0p, t1p; + secp256k1_scalar t0, t1; + + secp256k1_scalar_set_int(&t0, (t0i + 1) / 2); + secp256k1_scalar_cond_negate(&t0, t0i & 1); + secp256k1_scalar_set_int(&t1, (t1i + 1) / 2); + secp256k1_scalar_cond_negate(&t1, t1i & 1); + + secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero); + secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero); + + for(s0i = 0; s0i < TOP; s0i++) { + for(s1i = 0; s1i < TOP; s1i++) { + secp256k1_scalar tmp1, tmp2; + secp256k1_gej expected, actual; + + secp256k1_ge_set_gej(&pt[0], &t0p); + secp256k1_ge_set_gej(&pt[1], &t1p); + + secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2); + secp256k1_scalar_cond_negate(&sc[0], s0i & 1); + secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2); + secp256k1_scalar_cond_negate(&sc[1], s1i & 1); + + secp256k1_scalar_mul(&tmp1, &t0, &sc[0]); + secp256k1_scalar_mul(&tmp2, &t1, &sc[1]); + secp256k1_scalar_add(&tmp1, &tmp1, &tmp2); + + secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero); + CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2)); + secp256k1_gej_neg(&expected, &expected); + secp256k1_gej_add_var(&actual, &actual, &expected, NULL); + CHECK(secp256k1_gej_is_infinity(&actual)); + } + } + } + } + } +} + +void test_secp256k1_pippenger_bucket_window_inv(void) { + int i; + + CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0); + for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { +#ifdef USE_ENDOMORPHISM + /* Bucket_window of 8 is not used with endo */ + if (i == 8) { + continue; + } +#endif + CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i); + if (i != PIPPENGER_MAX_BUCKET_WINDOW) { + CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i); + } + } +} + +/** + * Probabilistically test the function returning the maximum number of possible points + * for a given scratch space. + */ +void test_ecmult_multi_pippenger_max_points(void) { + size_t scratch_size = secp256k1_rand_int(256); + size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); + secp256k1_scratch *scratch; + size_t n_points_supported; + int bucket_window = 0; + + for(; scratch_size < max_size; scratch_size+=256) { + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size); + CHECK(scratch != NULL); + n_points_supported = secp256k1_pippenger_max_points(scratch); + if (n_points_supported == 0) { + secp256k1_scratch_destroy(scratch); + continue; + } + bucket_window = secp256k1_pippenger_bucket_window(n_points_supported); + CHECK(secp256k1_scratch_resize(scratch, secp256k1_pippenger_scratch_size(n_points_supported, bucket_window), PIPPENGER_SCRATCH_OBJECTS)); + secp256k1_scratch_destroy(scratch); + } + CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW); +} + +/** + * Run secp256k1_ecmult_multi_var with num points and a scratch space restricted to + * 1 <= i <= num points. + */ +void test_ecmult_multi_batching(void) { + static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; + secp256k1_scalar scG; + secp256k1_scalar szero; + secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_scalar) * n_points); + secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * n_points); + secp256k1_gej r; + secp256k1_gej r2; + ecmult_multi_data data; + int i; + secp256k1_scratch *scratch; + + secp256k1_gej_set_infinity(&r2); + secp256k1_scalar_set_int(&szero, 0); + + /* Get random scalars and group elements and compute result */ + random_scalar_order(&scG); + secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG); + for(i = 0; i < n_points; i++) { + secp256k1_ge ptg; + secp256k1_gej ptgj; + random_group_element_test(&ptg); + secp256k1_gej_set_ge(&ptgj, &ptg); + pt[i] = ptg; + random_scalar_order(&sc[i]); + secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL); + secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL); + } + data.sc = sc; + data.pt = pt; + + /* Test with empty scratch space */ + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, 0); + CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1)); + secp256k1_scratch_destroy(scratch); + + /* Test with space for 1 point in pippenger. That's not enough because + * ecmult_multi selects strauss which requires more memory. */ + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1)); + secp256k1_scratch_destroy(scratch); + + secp256k1_gej_neg(&r2, &r2); + for(i = 1; i <= n_points; i++) { + if (i > ECMULT_PIPPENGER_THRESHOLD) { + int bucket_window = secp256k1_pippenger_bucket_window(i); + size_t scratch_size = secp256k1_pippenger_scratch_size(i, bucket_window); + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + } else { + size_t scratch_size = secp256k1_strauss_scratch_size(i); + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + } + CHECK(secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + secp256k1_gej_add_var(&r, &r, &r2, NULL); + CHECK(secp256k1_gej_is_infinity(&r)); + secp256k1_scratch_destroy(scratch); + } + free(sc); + free(pt); +} + +void run_ecmult_multi_tests(void) { + secp256k1_scratch *scratch; + + test_secp256k1_pippenger_bucket_window_inv(); + test_ecmult_multi_pippenger_max_points(); + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, 819200); + test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); + test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single); + test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single); + secp256k1_scratch_destroy(scratch); + + /* Run test_ecmult_multi with space for exactly one point */ + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, secp256k1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); + secp256k1_scratch_destroy(scratch); + + test_ecmult_multi_batching(); +} + void test_wnaf(const secp256k1_scalar *number, int w) { secp256k1_scalar x, two, t; int wnaf[256]; @@ -2566,6 +3002,61 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { CHECK(secp256k1_scalar_eq(&x, &num)); } +void test_fixed_wnaf(const secp256k1_scalar *number, int w) { + secp256k1_scalar x, shift; + int wnaf[256] = {0}; + int i; + int skew; + secp256k1_scalar num = *number; + + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&shift, 1 << w); + /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ +#ifdef USE_ENDOMORPHISM + for (i = 0; i < 16; ++i) { + secp256k1_scalar_shr_int(&num, 8); + } +#endif + skew = secp256k1_wnaf_fixed(wnaf, &num, w); + + for (i = WNAF_SIZE(w)-1; i >= 0; --i) { + secp256k1_scalar t; + int v = wnaf[i]; + CHECK(v != 0); /* check nonzero */ + CHECK(v & 1); /* check parity */ + CHECK(v > -(1 << w)); /* check range above */ + CHECK(v < (1 << w)); /* check range below */ + + secp256k1_scalar_mul(&x, &x, &shift); + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); + } + /* If skew is 1 then add 1 to num */ + secp256k1_scalar_cadd_bit(&num, 0, skew == 1); + CHECK(secp256k1_scalar_eq(&x, &num)); +} + +void test_fixed_wnaf_zero(int w) { + int wnaf[256] = {0}; + int i; + int skew; + secp256k1_scalar num; + + secp256k1_scalar_set_int(&num, 0); + skew = secp256k1_wnaf_fixed(wnaf, &num, w); + + for (i = WNAF_SIZE(w)-1; i >= 0; --i) { + int v = wnaf[i]; + CHECK(v == 0); + } + CHECK(skew == 0); +} + void run_wnaf(void) { int i; secp256k1_scalar n = {{0}}; @@ -2576,12 +3067,15 @@ void run_wnaf(void) { test_constant_wnaf(&n, 4); n.d[0] = 2; test_constant_wnaf(&n, 4); + /* Test 0 */ + test_fixed_wnaf_zero(4); /* Random tests */ for (i = 0; i < count; i++) { random_scalar_order(&n); test_wnaf(&n, 4+(i%10)); test_constant_wnaf_negate(&n); test_constant_wnaf(&n, 4 + (i % 10)); + test_fixed_wnaf(&n, 4 + (i % 10)); } secp256k1_scalar_set_int(&n, 0); CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); @@ -3168,7 +3662,7 @@ void run_eckey_edge_case_test(void) { VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); pubkey_negone = pubkey; - /* Tweak of zero leaves the value changed. */ + /* Tweak of zero leaves the value unchanged. */ memset(ctmp2, 0, 32); CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); @@ -3439,6 +3933,7 @@ void test_ecdsa_end_to_end(void) { unsigned char pubkeyc[65]; size_t pubkeyclen = 65; secp256k1_pubkey pubkey; + secp256k1_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; @@ -3460,6 +3955,13 @@ void test_ecdsa_end_to_end(void) { memset(&pubkey, 0, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + /* Verify negation changes the key and changes it back */ + memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); + CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); + /* Verify private key import and export. */ CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); @@ -4388,10 +4890,6 @@ void run_ecdsa_openssl(void) { # include "modules/ecdh/tests_impl.h" #endif -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/tests_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif @@ -4420,7 +4918,7 @@ int main(int argc, char **argv) { } } else { FILE *frand = fopen("/dev/urandom", "r"); - if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { + if ((frand == NULL) || fread(&seed16, sizeof(seed16), 1, frand) != sizeof(seed16)) { uint64_t t = time(NULL) * (uint64_t)1337; seed16[0] ^= t; seed16[1] ^= t >> 8; @@ -4431,7 +4929,9 @@ int main(int argc, char **argv) { seed16[6] ^= t >> 48; seed16[7] ^= t >> 56; } - fclose(frand); + if (frand) { + fclose(frand); + } } secp256k1_rand_seed(seed16); @@ -4440,6 +4940,7 @@ int main(int argc, char **argv) { /* initialize */ run_context_tests(); + run_scratch_tests(); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); if (secp256k1_rand_bits(1)) { secp256k1_rand256(run32); @@ -4481,6 +4982,7 @@ int main(int argc, char **argv) { run_ecmult_constants(); run_ecmult_gen_blind(); run_ecmult_const_tests(); + run_ecmult_multi_tests(); run_ec_combine(); /* endomorphism tests */ @@ -4509,11 +5011,6 @@ int main(int argc, char **argv) { run_ecdsa_openssl(); #endif -#ifdef ENABLE_MODULE_SCHNORR - /* Schnorr tests */ - run_schnorr_tests(); -#endif - #ifdef ENABLE_MODULE_RECOVERY /* ECDSA pubkey recovery tests */ run_recovery_tests(); diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c new file mode 100644 index 00000000..141645ea --- /dev/null +++ b/src/secp256k1/src/tests_exhaustive.c @@ -0,0 +1,511 @@ +/*********************************************************************** + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#undef USE_ECMULT_STATIC_PRECOMPUTATION + +#ifndef EXHAUSTIVE_TEST_ORDER +/* see group_impl.h for allowable values */ +#define EXHAUSTIVE_TEST_ORDER 13 +#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ +#endif + +#include "include/secp256k1.h" +#include "group.h" +#include "secp256k1.c" +#include "testrand_impl.h" + +#ifdef ENABLE_MODULE_RECOVERY +#include "src/modules/recovery/main_impl.h" +#include "include/secp256k1_recovery.h" +#endif + +/** stolen from tests.c */ +void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); + CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); +} + +void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { + secp256k1_fe z2s; + secp256k1_fe u1, u2, s1, s2; + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ + secp256k1_fe_sqr(&z2s, &b->z); + secp256k1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; secp256k1_fe_normalize_weak(&u2); + secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; secp256k1_fe_normalize_weak(&s2); + CHECK(secp256k1_fe_equal_var(&u1, &u2)); + CHECK(secp256k1_fe_equal_var(&s1, &s2)); +} + +void random_fe(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} +/** END stolen from tests.c */ + +int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, + const unsigned char *key32, const unsigned char *algo16, + void *data, unsigned int attempt) { + secp256k1_scalar s; + int *idata = data; + (void)msg32; + (void)key32; + (void)algo16; + /* Some nonces cannot be used because they'd cause s and/or r to be zero. + * The signing function has retry logic here that just re-calls the nonce + * function with an increased `attempt`. So if attempt > 0 this means we + * need to change the nonce to avoid an infinite loop. */ + if (attempt > 0) { + *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; + } + secp256k1_scalar_set_int(&s, *idata); + secp256k1_scalar_get_b32(nonce32, &s); + return 1; +} + +#ifdef USE_ENDOMORPHISM +void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { + int i; + for (i = 0; i < order; i++) { + secp256k1_ge res; + secp256k1_ge_mul_lambda(&res, &group[i]); + ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); + } +} +#endif + +void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j; + + /* Sanity-check (and check infinity functions) */ + CHECK(secp256k1_ge_is_infinity(&group[0])); + CHECK(secp256k1_gej_is_infinity(&groupj[0])); + for (i = 1; i < order; i++) { + CHECK(!secp256k1_ge_is_infinity(&group[i])); + CHECK(!secp256k1_gej_is_infinity(&groupj[i])); + } + + /* Check all addition formulae */ + for (j = 0; j < order; j++) { + secp256k1_fe fe_inv; + secp256k1_fe_inv(&fe_inv, &groupj[j].z); + for (i = 0; i < order; i++) { + secp256k1_ge zless_gej; + secp256k1_gej tmp; + /* add_var */ + secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_ge */ + if (j > 0) { + secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + /* add_ge_var */ + secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_zinv_var */ + zless_gej.infinity = groupj[j].infinity; + zless_gej.x = groupj[j].x; + zless_gej.y = groupj[j].y; + secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + } + + /* Check doubling */ + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + if (i > 0) { + secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + secp256k1_gej_double_var(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + + /* Check negation */ + for (i = 1; i < order; i++) { + secp256k1_ge tmp; + secp256k1_gej tmpj; + secp256k1_ge_neg(&tmp, &group[i]); + ge_equals_ge(&group[order - i], &tmp); + secp256k1_gej_neg(&tmpj, &groupj[i]); + ge_equals_gej(&group[order - i], &tmpj); + } +} + +void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j, r_log; + for (r_log = 1; r_log < order; r_log++) { + for (j = 0; j < order; j++) { + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + secp256k1_scalar na, ng; + secp256k1_scalar_set_int(&na, i); + secp256k1_scalar_set_int(&ng, j); + + secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); + ge_equals_gej(&group[(i * r_log + j) % order], &tmp); + + if (i > 0) { + secp256k1_ecmult_const(&tmp, &group[i], &ng); + ge_equals_gej(&group[(i * j) % order], &tmp); + } + } + } + } +} + +typedef struct { + secp256k1_scalar sc[2]; + secp256k1_ge pt[2]; +} ecmult_multi_data; + +static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { + ecmult_multi_data *data = (ecmult_multi_data*) cbdata; + *sc = data->sc[idx]; + *pt = data->pt[idx]; + return 1; +} + +void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k, x, y; + secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 4096); + for (i = 0; i < order; i++) { + for (j = 0; j < order; j++) { + for (k = 0; k < order; k++) { + for (x = 0; x < order; x++) { + for (y = 0; y < order; y++) { + secp256k1_gej tmp; + secp256k1_scalar g_sc; + ecmult_multi_data data; + + secp256k1_scalar_set_int(&data.sc[0], i); + secp256k1_scalar_set_int(&data.sc[1], j); + secp256k1_scalar_set_int(&g_sc, k); + data.pt[0] = group[x]; + data.pt[1] = group[y]; + + secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); + ge_equals_gej(&group[(i * x + j * y + k) % order], &tmp); + } + } + } + } + } + secp256k1_scratch_destroy(scratch); +} + +void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { + secp256k1_fe x; + unsigned char x_bin[32]; + k %= EXHAUSTIVE_TEST_ORDER; + x = group[k].x; + secp256k1_fe_normalize(&x); + secp256k1_fe_get_b32(x_bin, &x); + secp256k1_scalar_set_b32(r, x_bin, NULL); +} + +void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* Verify by calling verify */ + secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + secp256k1_scalar_get_b32(msg32, &msg_s); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} + +void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } + + /* We would like to verify zero-knowledge here by counting how often every + * possible (s, r) tuple appears, but because the group order is larger + * than the field order, when coercing the x-values to scalar values, some + * appear more often than others, so we are actually not zero-knowledge. + * (This effect also appears in the real code, but the difference is on the + * order of 1/2^128th the field order, so the deviation is not useful to a + * computationally bounded attacker.) + */ +} + +#ifdef ENABLE_MODULE_RECOVERY +void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_fe r_dot_y_normalized; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + int expected_recid; + int recid; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + /* Check directly */ + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + /* In computing the recid, there is an overflow condition that is disabled in + * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value + * will exceed the group order, and our signing code always holds out for r + * values that don't overflow, so with a proper overflow check the tests would + * loop indefinitely. */ + r_dot_y_normalized = group[k].y; + secp256k1_fe_normalize(&r_dot_y_normalized); + /* Also the recovery id is flipped depending if we hit the low-s branch */ + if ((k * s) % order == (i + r * j) % order) { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; + } else { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; + } + CHECK(recid == expected_recid); + + /* Convert to a standard sig then check */ + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } +} + +void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + /* This is essentially a copy of test_exhaustive_verify, with recovery added */ + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int recid = 0; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + secp256k1_scalar_get_b32(msg32, &msg_s); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* We would like to try recovering the pubkey and checking that it matches, + * but pubkey recovery is impossible in the exhaustive tests (the reason + * being that there are 12 nonzero r values, 12 nonzero points, and no + * overlap between the sets, so there are no valid signatures). */ + + /* Verify by converting to a standard signature and calling verify */ + secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} +#endif + +int main(void) { + int i; + secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; + secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; + + /* Build context */ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + /* TODO set z = 1, then do num_tests runs with random z values */ + + /* Generate the entire group */ + secp256k1_gej_set_infinity(&groupj[0]); + secp256k1_ge_set_gej(&group[0], &groupj[0]); + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + /* Set a different random z-value for each Jacobian point */ + secp256k1_fe z; + random_fe(&z); + + secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); + secp256k1_ge_set_gej(&group[i], &groupj[i]); + secp256k1_gej_rescale(&groupj[i], &z); + + /* Verify against ecmult_gen */ + { + secp256k1_scalar scalar_i; + secp256k1_gej generatedj; + secp256k1_ge generated; + + secp256k1_scalar_set_int(&scalar_i, i); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + secp256k1_ge_set_gej(&generated, &generatedj); + + CHECK(group[i].infinity == 0); + CHECK(generated.infinity == 0); + CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); + CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); + } + } + + /* Run the tests */ +#ifdef USE_ENDOMORPHISM + test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); +#endif + test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); + +#ifdef ENABLE_MODULE_RECOVERY + test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#endif + + secp256k1_context_destroy(ctx); + return 0; +} + diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index 4eef4ded..e0147500 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_UTIL_H_ -#define _SECP256K1_UTIL_H_ +#ifndef SECP256K1_UTIL_H +#define SECP256K1_UTIL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -57,7 +57,10 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * #endif /* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#ifdef VERIFY +#if defined(COVERAGE) +#define VERIFY_CHECK(check) +#define VERIFY_SETUP(stmt) +#elif defined(VERIFY) #define VERIFY_CHECK CHECK #define VERIFY_SETUP(stmt) do { stmt; } while(0) #else @@ -73,6 +76,14 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ return ret; } +static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void *ptr, size_t size) { + void *ret = realloc(ptr, size); + if (ret == NULL) { + secp256k1_callback_call(cb, "Out of memory"); + } + return ret; +} + /* Macro for restrict, when available and not in a VERIFY build. */ #if defined(SECP256K1_BUILD) && defined(VERIFY) # define SECP256K1_RESTRICT @@ -107,4 +118,4 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; #endif -#endif +#endif /* SECP256K1_UTIL_H */ From af4fbd9e198c6456134695e4b2435822125aaef0 Mon Sep 17 00:00:00 2001 From: Michael Bos Date: Wed, 11 Mar 2020 22:23:34 +0100 Subject: [PATCH 2/4] Splash screen and icons Updated the splash screen and adjusted all logo colors so that matched. --- src/qt/bitcoin.qrc | 4 ++++ src/qt/bitcoingui.cpp | 6 +++--- src/qt/forms/optionsdialog.ui | 12 ++++++------ src/qt/res/icons/address-book-sidebar.png | Bin 0 -> 6687 bytes src/qt/res/icons/address-book.png | Bin 16580 -> 12141 bytes src/qt/res/icons/lock_closed.png | Bin 16675 -> 9247 bytes src/qt/res/icons/lock_open.png | Bin 16752 -> 9571 bytes src/qt/res/icons/message.png | Bin 0 -> 12151 bytes src/qt/res/icons/remove.png | Bin 17709 -> 15274 bytes src/qt/res/icons/send-sidebar.png | Bin 0 -> 6837 bytes src/qt/res/icons/send.png | Bin 17085 -> 12608 bytes src/qt/res/images/splash.png | Bin 40272 -> 42011 bytes 12 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 src/qt/res/icons/address-book-sidebar.png create mode 100644 src/qt/res/icons/message.png create mode 100644 src/qt/res/icons/send-sidebar.png diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index c9f13fd0..bf7d777b 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -54,6 +54,9 @@ res/icons/digitalnote.png res/icons/digitalnote-16_testnet.png res/icons/mnodes.png + res/icons/message.png + res/icons/address-book-sidebar.png + res/icons/send-sidebar.png res/icons/dark/connect0_16.png @@ -128,4 +131,5 @@ locale/bitcoin_zh_CN.qm locale/bitcoin_zh_TW.qm + diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 9ed3d51e..4c5f3696 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -290,7 +290,7 @@ void DigitalNoteGUI::createActions() receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(receiveCoinsAction); - sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send"), this); + sendCoinsAction = new QAction(QIcon(":/icons/send-sidebar"), tr("&Send"), this); sendCoinsAction->setToolTip(tr("Send coins to a DigitalNote address")); sendCoinsAction->setCheckable(true); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); @@ -302,7 +302,7 @@ void DigitalNoteGUI::createActions() historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(historyAction); - addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Addresses"), this); + addressBookAction = new QAction(QIcon(":/icons/address-book-sidebar"), tr("&Addresses"), this); addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels")); addressBookAction->setCheckable(true); addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); @@ -313,7 +313,7 @@ void DigitalNoteGUI::createActions() masternodeManagerAction->setCheckable(true); tabGroup->addAction(masternodeManagerAction); - messageAction = new QAction(QIcon(":/icons/edit"), tr("&Messages"), this); + messageAction = new QAction(QIcon(":/icons/message"), tr("&Messages"), this); messageAction->setToolTip(tr("View and Send Encrypted messages")); messageAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_7)); messageAction->setCheckable(true); diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 4e47ad22..846f3087 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -26,7 +26,7 @@ QTabWidget::North - 0 + 3 @@ -465,6 +465,11 @@ + + QValidatedLineEdit + QLineEdit +
qvalidatedlineedit.h
+
DigitalNoteAmountField QSpinBox @@ -476,11 +481,6 @@ QComboBox
qvaluecombobox.h
- - QValidatedLineEdit - QLineEdit -
qvalidatedlineedit.h
-
diff --git a/src/qt/res/icons/address-book-sidebar.png b/src/qt/res/icons/address-book-sidebar.png new file mode 100644 index 0000000000000000000000000000000000000000..fdaf90fce5ce69ed6d82f16ad3964efae0da6b51 GIT binary patch literal 6687 zcmeHMdq5P`8Xv?f%0n|sL=v|}Gs|ITW@jI>?#gRX7F<9;Tr#uSnOPXv-C1`BcOmi- zVOK5977fV`pQ}H+qV%FyO)G6J9m22>#fYH-yUlWpLlT9xwDhZC7YK` zS>cX(wHopF8(lKAa<5~+mh*EbrMma?u}fZzTldM7ypZ$f=ee9M@mmcwlb5gTjdHJC ztNeVEd-}TLY0W>+ZAO1S7~p(?_3>tdgIn|thABj&QMRU^=t4=YaFzAd|*u_ zxAu`o8U}=ETPg}FHbj>U%Wlwl+~msUnoL8;zV~-vPi)Dm z4~Wh&>+`?gns~WX@nf*TCuTA>N^UqgwM1DOzGc|F59?AW{~r^b>$m$xi+8Ux1pcHN zzk6unl1enJKhL+WHV{eQ`u0p%G^)f$E)KOVJ$-B-wV^2MSL|etPwz#qF8DO&y&jo~ zbFclq>9e=jRE~HrH#7aqN?B5JmSgYY)1edeBbPiQm)01+*y&!It#C@73kccKziL=W zz|N!*8;u9%?tk>1r`5Td%dbZaE^Mmr8`U^I?7*s(Rj?xO>%_Iow(>>SHO_$JFMNOD z-Qd-HRr~myM+I7+z## zvRSJ}+_JS+EMjSmc%n>?=xuRK4x3PDXVMFkGpNEmilD_&qy5z`6(F!MJSlQn%vOiW zr4f60Rp7HQED?)55I#>MHt17Dah#nI;gNVG0>``9X_$DlzesJTO{z5Qm^KP6mAS4JT!7vygU`K(KCta}B5g|}`Ikb#}va>dx<*XuslQeSq zyhbbra#0&OkW%q3FxX~5xcAUIcv_+ZH#qPI03;ZKC}9MHF+$Q=A4v83c5SPpEs7wX z5*KNcppl5gV!1`b!N*VQu-B!ABLnmsNgCte^6eB8KaH{S5uJ_N%=wPaHuD{fFyxuH znKntlq&${8>x|XuQ`>cfFlMtBn@2-HcSh1wJIeiaI*k~ML_Fl4kyJCu zn>f1#EML}2b52KxD1)^y={zZf3zaFQgdD{cIEpC|Ox^*?Wb6*Gj09E`iS!C+N;L*h zlAxMd3z^MGY}Ra#hLCqv9B1b2>7a)&8nIj^lX^Y%h*DV>V>W1kU8|Rrz&i9i!mQhc z?S(gs#)V~M&KHI!SXnStuPKj;p+lw-E5Hgz5D6;0 zcW7sI3jwvFinB8$&uGB~xDiwVBPfjG87QHWN>w-lBT7{pVLO_$XKYc zr!l{Cjmjad*$g-cwCw`jxr`E0nT)1sm^7hA7$65&swN zVJcLilHoVqQ%i*N>&sV^x1gO#p`*3=`&1Pm9`>mbqW@o@8@c00pMkMWzBW-;g z6yP8E)3!hSktRf<2S)BIz7N9nAYAtqf%^hKsICX$x~~Y_7x+PS{olgn-|>YeV+9W{ zPVjZ*cHg?Uz*n8Uj7ej)&<){Lv2B$bjP$W3WH}%xAXvD3pz@^y!Jr?n)5rTY`35}N zUp_JN@FfWH*{0LRWPtw&yp=V-I6Ckzr#EiCv1nOvU~cS@ylwju*f%N>`Mlj{7hGm$ zK_{T$ke|}W)%ffyU#|F<asw4B@c~nO9TFOW*v|{X|`#IuNGi asv(54 literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/address-book.png b/src/qt/res/icons/address-book.png index 03bae78ef8ca9557e8cea33144f469f6b62ac2ab..6f7a1706c35835e42246e0780c01c63fde07ab43 100644 GIT binary patch literal 12141 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 IQ=b3xuVP@}6951J diff --git a/src/qt/res/icons/lock_closed.png b/src/qt/res/icons/lock_closed.png index e827c229c304a284f3c10a6e476b9b9f7451f266..3def8c9604550c6d4c3ac03f8f823238c38852c2 100644 GIT binary patch literal 9247 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 *-i_!n~SgNRgvUkR)r`Iyniqm-( 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 literal 16675 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 aGJS4}_V(@3UYX2GD{~VY+SvHeXp}~?VR1u z{oMESoZo#v_jC5gc`7A2A&ecx1^^%|DN&n7ULCG)NHBRmszyE`FQd$fi>v?;8sYi| z0MFOm3ji~oH)doJS-SZ!iWdnGJ)VmR>_uj>HvlMS+RX@BfDznWEZ=BS@va>@!s8nC zDqf~k2kOik%wS9`vta3E$r)%_0jkjRW~$jrJ4`w#!U%+GFDf)yVY`aw_6w80UClxs z*WHCEQ1Rkj19G!;DO?S1!MIX^jE{=Ma&D|bAd)KNkYqX+0!1<*s1S-Id{6{~3K$e| zy&s;MP5x3^^m%Zac8+&AQd02@1Yw4SLYvJdu!#k@C0{5~C=@~v5<(E4?7_E|nh3zAVph~*G!sVL#C7>aa`9q9#pAgK@_oGbRb=)JWU_kMkrah?#4HpEK;ckE zdemoQF18f9r=~}RSRqz~nFuRsCmPbuY`_WJYQTpX(x)DFU@|5;op0m_bEkqQ zLQ3*pVT}bt2;7o^c3F~{ z$QMa6L<(3eh9w{$l*1tC=fu;K;zNh)jd`X0KID86#D|~^k<^{jq{{&xem$u^$n~Q~ z2;`2u`1kemqetO9+){)PYGVE)oDFU7Et$RUT9%G2y}h+xQD}76Br{^MVy+dZ;`J{% zUlH@wD3^_U<-!Q+s%C1`wIDFPQg~bIz_fgpUNht10Nxp8kAFY&;m5EUFcaN^^0;#M z8s3Q&&m(Mz1&hxob7GjaF7;pQ9{Mf9frYO3jg68C>*yC|U*=1qi*!;G*Y4(K5IwKgNvRI zMa$r#0HGHdT=aY>S_T&d2))SQqUS@=GPo!}=tTw>Js*me!9@W=FEY63`B1bBE(#EO zk-z4D~(%+VM-t24nRoQX4S+VQIv{$%2pG;pJ7ofd^WBb@oOG2O@**W3ho@oJpJhJ%) zt95Fe!Vq|_a@@r1@r~c9a|#ld08_rWoU`iuhiArTI!#W6^SbeDkE%=3#YstZ{9p}z zGd$~&3uVhHr#RMU2Xbuj?}cAXn%G+fFPn8=qmngtt<@3hm?3`rT6RuY*R!nl=H*V6 z^VRC}w>Sqze6t6*xm4CQ{!RI=8#Y!fD-aJuI@zx)O~?i|h929z%tm6NpK;CMrF7M_0bO!)%=Uv$7Z zk*B|U|G{oxG;3z^hHH>>f%9xtPo`sGeXBI?pmHPFo8TypOQ?26TqmlagbmA|)3hpC z+Y`lI%jCD#9t|-^bln_#{!l=#ZgwGePlFiU$8@p2j##olEJiI>O8+H^sB$8##v#^#KTHQ!I}}a7MC~sR z?y`NF-pn?0y4EK+&RLeO{HmfNY}LarKlJmZY|X{p>2d3xdzOnYVR!zv<8)?FVoBhd zPktVIu6662CF8i?MsWqJrtX_rOA7U;Qh}g*{EnL6UrgLGtGT27qZ6~wTs{A*_MHVC z$Km9@>=m^aTl!9aR$mblcTA<7@kr#^H&59toO;#vr+O<5jUQj>frB0kDGZQ(E$zI!k-U!SJz8bJl5!yJd`uN_m@cJNoSZ%@8KGbyY#($P&jUX`d34Ghc;y)|q zUSvHG-Er;csLM}pjlH6(jBXmaqHRjM%z0F#J_64lxAZ`8@6I*pO(Qh|sdMsIX3wJZvL z=_}{Q&m>)uSL_A~Di1k2oA8N6qqn_2xvepalVMB&Qr*Yb0GsPQoV*n8GI=ol^3Bbnb=qZ}6VGWXct75FERa*RuwhGj zuw#!VDrDP!IB3(B{K{ypEoQ-y+E*0I-=5T->KJo9vTxl;z-NZoe3rl}^{H{CNTLXY^wWInzysIpZtiwRk>}2g5vvOAc8_tCAH2?qr diff --git a/src/qt/res/icons/message.png b/src/qt/res/icons/message.png new file mode 100644 index 0000000000000000000000000000000000000000..e46c16539aafbce7c9ec9d3df228e439a027cc56 GIT binary patch literal 12151 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 literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/remove.png b/src/qt/res/icons/remove.png index 6fa13322b1a20c6b41127e3e41e0ef5be6aff627..7ca265d6e488c16db969b1c22ada6ad8b1bc2ab3 100644 GIT binary patch literal 15274 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 F{6D5Msb>HH literal 17709 zcmeI4dpuP6|Hr3Dp|(Q03Zt8?xtqbn5F^)-TsET%W9AGKW`>z@t9A)X5~9Uw!&WZe zOj53`NXn&)iXv%?O^GO7bwPd4xOdWd>^^?``{Va}%(%?FKkv`${W<6Pet+KQ_~Y1T zXKOx3VTl3)ftX`yLA3|py(K@h@D@+n>^owEP|LZo47d{e-a zV-f5JI0V}|GK0OC`YfaoMZqAD3jo~RmFGJ)8 z$$}crG&>Dbo*$q=M3YcV96?V*S09Zd>g(Zk)@k6eI1&b{kHP7nusAYSpNz$6jJ}W* z1@M!BAB#=4r*0fw4zvuBo_Cc`Kn5R!Lt`;h ziCD~W4PWHvJ$z^^CI;{Zd;qRc0P1j4>iC{KAy44R`^J*v?r$y(=7dHYUwg{q_3@c< zX@StpA4D*UbV{YbF^CUf>;VB!Wi zxD-Y*WB{Hk+0+kU2zh>vJf1gYq{{5Z5Nep3N~%g%W6c&0m&FSZXd7Ull8JmzL<6V{ zAwZER!AeBobR2Q|WCDS#gGFKW$XM*8AR{v&F=#v%haEH)Ll1?+qwsh~98pr!I$&{6 z#F#V_8Ux%vEQXNrx1vm*J1Gu}NoMo>d>BFs$A{qoVE9}Q1I)zWq?zMYMK5|?GYLcjz+@6o`glD&iiFeAMd^{)Sd=cH zr^|46*8^B=(lA6CZL<8U&{Q5%B-t≈=&P2A)OI(**tfvYAFkj0IbiTNp%ZW?{F`30DQk3 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 diff --git a/src/qt/res/icons/send-sidebar.png b/src/qt/res/icons/send-sidebar.png new file mode 100644 index 0000000000000000000000000000000000000000..db6269d6f3a8973ad225560f2cb82e7f277b216b GIT binary patch literal 6837 zcmeHMc~leU7LQn=0<~`7g4Q&+)aoQNnM{(ICJM4>)CdYfP+K!w$Uu?_lYxL%A60AB zw(5H*R;sURa49ZFk4xQ)$EAu^#nw`-;!@Yzp6c^ywOD=MBnYUuz4zL`BxeTZF2DQT z<-7NrFg1Bd|5rjghRS5JS4;!qhk@S?>3TUB+-KO*zm~~@ei)N#5r>gpxm)0EoP(8% z1#VW(=5scgEdTf~bId~Y>*4SJHjkQK*mcsb9J{^jLa^sff%VAr`GdD;3VZzW!r3z6KATkan}s zQqhlhifSOA`84DMy{`acxy~QQjKY7Q?_+RCSBn zCZDs%AEUM`K3o$~Iqt#-A>FImc3BtYt7(7H>BZPLX78;2_J_2zSEq-R&cb^8+Pe}? zrS*JcI;5Ra9eX{7doL9E_O)5dQWnQv%!*dMB*ij#f*$ zwF}!lsONg>$h5-|zFvkbXi=MrM){R&rtuA;7l1;nwWHM`;x>@k9RFD{_N!EI~+G7 zCtS!`RMcTgj-urkCRy{Zi!#K4Q+sUM*E@30poQUCrEP{RHHE+QjcLV1Wu8|UErgYf z|1j#_v{9d2y4!3MTdcdi$HR&u7tuI+yh?w@{Rp-k5H4hPEIVjfJ;yi-XsJjE*Woo=uVWHLkFd^bsF zv!a}0GdY)0@#~f^6>^R-D$+4CY<9=7c5c8JflV1RB$XbMP2-HBZ=X;@J^=untVqi9 zoer0W$TuqdxCHoHBC8Z~zlfM^R9MW(@;F{#sQFIe3mDlT4dQl}WWU3Gx$5pUerB*{g0`e5NL^2<8d7>qV07g9Pp#{z@a=c3} zVUiS|D;gCFz?av811_DA4~Vq}q-Q_8M`Tnc@Sp+y00EU6hV>AvhSa#Kp+4Z6&2`!? zPi+)IJXQImTZJfLmDBlvhDS`utGCyvh9?zt8`Ut@!{-V#n~=x4#OQ`b-Hu#OLz}rC zRwDV=?O<#wuqeOfhC2OC=HxmZDU6w%)9u%gq#H^ybe)_#S8(`c7+S?TSSMJB2OuL4 z$V*+ZPU8W8B+erXaoc&3_t<%N<2rThM-)ZQ_82=7=Miz>R^t}#=f&@{KYv6#Pv=U` znc|HKKv6OrL(sIA)~eMwq|s6sgxEAFq^EEe(omRMN76bijp!Rdm|Px_bkXd62o69X z8WACshpEd5lJar2&PAIErP*1jTQqHUoVu#3LdbHBvb@eYW)m` zCK3T8396ZMl9{Z^?aK5sq`VVxyn`1~Ko4P!3N41ASUoG5%V!;ycwpBR07c+HDE*3l zZbl>Ay3z<>n|TI6qkdSa0tgU4kV8`1?!c9Ly0noTxe|G}ivx>Q*Rw43JflJfJceNv zBHimnGM*>`s)dLXSW;x;!3D5kLV_cikR(V9B!1NTS z9+ESF$eYc?0HDhY1r6+{usMOJKzJOSe{{&@{w7Y4bfDH~e*rN59D+Cpm|P3Z%8x^tAjFuQ8dHL44AhUarx z_f(g`w8o`vs8$mioIo%L)=As&FK`*vAzB0{F-T9^7zkxF7)0rCEtmpo6vM$-K{3sP zd3vTSKa0zawu-;NWl{|?t3fpoMeD$bL}(JiQ5y`AHkie5y-o+ix+l8aADl+~jqquC zRf7hILI{$oMhHw#AiBRKqcEeRQ3{7>FsUGoO=E*7(4`@S!cZM<(=ci}Fozyj#Q%kR zY68&{>N@ufD(M7!zaJT-Gu}fT%OITr36nI5Q*zyI2geEzcC!1O{V{S4^!Gs_uoPwvU4h z{h2?t^Wo1lA(y`}@?7zK5v~{EdaejOm+*_~dJ(SYiokOTzo@SNTew2&ztUt~;N`^& zzOdA%H#2}QJAP7STd%A^4z&2VsD+<=zGgq-P zZer1EW_iKF=3P~qZj;Z(cf~D{%f7V-RfL&i3KsTkx%|rR8$wgh_(Qv#X$z@lE z%}idGv94^-;xE6Xvv2JU-f$pie9fu!N@g0i{f~9T#96J}@ zv#rZBhQIw8GjQ_x@bzt+^Mgko%e2iN*v9gXy^LtHJaNa-;hlRO?VPzLHJUpE{` zMDdX$t4s9Ptt8#FX4+{ni+64wN*)}0 zIi=cEwIgw2u6#=`hv9D0veIhbKXOMaEOW}siB5CV_g|V6k<+<2N510b@PkVR6kCp! zyH4rWo>*gu>UWGvn3!;K>W1-=R_%m0E62Zg{^;H2v(meyF7Wxjnbc= zU%I3|le*03Bhq%|TJqNYd(ft7sa4bSESeK|p#_ zREj9QDuQAG`2wEn@!osxx!-xd^6QdkhwL@)yt8K3%&hh7onU03$w0?N2LJ#Vw6)Ys zNdMgqE*fgm_ho0xegJ@rHqgw9XoB(sdf`2tac&qOF~AE0#Q5W!0RaD3Q&+8hh3?%| z--le3rrhrL8oD{p>Hpc2Pc7xiHJvoja<6(-w~n(0;GS&1`ir%&{nhOKS;K)-SF?5c zK`y<8FC4e>`6@%c%fHS~-g)=!^x%%)#^QMYqNKbe)x)?Qif81~ z`E?sr?`vy6+QG2=ee$s8nQh^RJ1HtHw=(Rz27HF&g_8V-dl0Y^>IaeN56r}#Wfc{1!sZG{^p9yHIs$@v%riuq2gQS zpCva5jrPg6dXAq~ws#`DmrA}cz`8zr&Gu&V?5Dl6Q%(uPp7x(N_JrOB*2KQOS}4>W zQ!eQjObZfMl?cvu0==)_w@Yl^ao-6|*O%zEh}yZ7D0_DEs^nJHiT$4O#h3x(Wu(ih zOSRP%OS1Z-7=y4a36{45+@r+VphtaIn(FLXxVs&iP&eIbCpPUIg?36B9`_SwLY``% z3-NxKmJ>j=Nx3?X6(sWNIV}k}+Xs>Z%w0O6$TK_qUzMrtbV6kb-TE{+b7r@KwsPKX z1ciJU>{X&q(Bh9%akW_zI@77Pmtj>=T%dAM_P0^hGL&!?-u=Sl5= z2w|jeXMN7ZosfCW=l+cumvv>@v`q%OvoBvtI)Mp~{M3_EBcXAtPt>I$AXgxuejzRG zb{EWASDS9_GRc2meck`MrPcn?P*T?yQ(Jpf>~mc^RMK*ieQ(g?+@=dN%hgJbxzCup z)5tyXEtc0NE)|a1bT^x9c|57FNVC}+a4CD<-xuwlCC~0Hq%!3#1-`kq#+@_2I+i&? z)~6LTQ4sGp@$ucsE7WX?_?TMeTpOfS}?>;^ka%IUvo={MKWB5pQ~)1rgqbYG{6 zluqlyC~Jro#up?_CuA6ci4<7=Sdd=x>AULQobxEnI;-EOUMY^=Ry-$S zG|GKeA)V`8O_83EAc1?xmRl#8k-?5GpmdDz!vB?2^t=74fTb)*59UcI50bf z8E=90tVwhgj2kRxiftihuz~|KD+u1ZO|z7zE9XaK%d;A|9p*g}>BL}ysa#X0TiahW z$@KRJ!}r-H2kaW;;7=iP4AKaWCAk@$iOyNnL{7=GPGsrP8)$=~QL4C++9MkptaU1Z zi)nCm$F#zrcLH6in*PuBX#?P>DBlznwVTrS=mmldiS05u+ol;>`1rT3FA)q^&zXW~ zC^4v@S;jMgA09ZCA->eieM-IK=729|D>Jtr9IF8rn-%pt(L-fF^Olm2Ov+=6EvVT? zo!`5g*!iZXD4q3f%zR{%+{$l5=2a4%U=DVqxo2p%Sj67JI(1LMi1+G4Z{1sy)4g94 zpe<8=u58{grC(dcnG%pEae%EWpf#uxP8rj*Zc_tmm}Kw_{`C{l6T%Ra4rvitL1j10NQp7ZKlNcj{tj2 zebQl!Uo&6jjZ8)niEpSOy({cG_d2f__lI>ny|yD&*1MGJU;c@fDX_>hVEz1u=R$YUxApCC5f9N-@w)7`h^sSBzVLH$;}r&C3k* zsARvKN{CK6e2|+*s)Fh|HD*3#B1e;p;m5d5@OZ@ zf$ETPZVkfhm+h(bJC{4#TgyK_l%Cd{n7UE2Gv=Fo-E(``>b(H(5e0u3CC`%^@NiAEjDecC^F9_a&Pwl)4*@;`{w0PaYYzkYyu(u=DR%srOp-(rVe>M0bR%-!bivHn>n54p9?kmYrFH-*T*D^Y(3s((W-qOE-0IFyFso^Z`H1HJVz(D-c!qSu@Tyn{tGj>F+Ku8YGx2Iku1z}=sF zdXB;re~;6+!RzL7TFxBH*~0KQqD$H)kXb$iPb}8(s40+l6n3*LbcVm?^I=?+*>tU zY6dHcw#v_|d6x894>bDRQ&D9{@`Y_C&Bv%ijaSq{X`XVaggD?}>dVJMGi3S)R zYcU-#r{^L@;+$UvUE8ZSbX4`^K5l_xv<;gUL-YZytm#kuRbKX5WIS7< zW}{cduBQ;^qAe1x@C^aZ(`2wT2o&U!vs62Ag{e}`_!+fRQXZ2xiHm4b5}rE_@Wka$ zE;XB?!pt;ex<>3XZSjK<1e0Jyf3IT+?9-IJ$dX*}sS;$gWRRBu((2jyOi0wmGK%ZKfja`;NAbNlu`+K+$S?!XvUm84sQ6AV`Dis zK!l2eO6k_F=LseIFZ&UNw|4hi2Q|ObE1udnH=4@R>#s|{fY*Hyny>I?>b{-i-SWpn zp7Hs8V)CuR@&Z_WJBMOnZ;9OLq8XZ4%?;FeTk74s}fW;e}99tG{0&B<8nRW zA$RiiXhE)uZ~=YYYgtQayhY%(<>DId>dc4%0pW_^5({gzl4Lk}G7>(1!tt)1#R=mf z2G7J!TUACEy>2${OS+FCW*;8=cJpnYDJ1tO85NmbU_eZ(dWr3nE$LX+!B?^+sIDB> zkvEU5C*%YvTRY{iTuT-e(2>E3)FqYWSR7>`d>J}EZjB9(9-GhC;>uE~A9mMrI?sNQ zaV3zIs?~&-%tcAr*&}T#)3_W=m)Q_Y317XZ6_TOo!!|r2BFu%?VZ24rBXQ*%J*`QU zVBB(Yn(zg}lAwQ5y)5#oEXxv8Ha41 zoj0DB8n)P0v3Rm#r4PIP7O_jSHCzdhE0_^Y&3{9EM+wm!b(*2|A=^V@b^CO}c1h>9 z`o_sM?aSBnYA;dJn={#D&O=1V$Dj9Exk>5wh))!$3L9lHj9k4KH8q$G)}Va(lHPd& z{*K-4YOSD+)Uv?Y8w%%SBP(MKvUDsGsrspv^Sms^7qKql!CB2WR6r7dGtX=unrc?2 zSM%F~$Is;p?7`p)*Odhs2a)GUWcTTCV%OzGIdHU#NB;wAd&c}wOpvrw6AFio~CMV^R9sn2p zpD?#<4@I6ec2T&im0#c>l3QKuP-e>S0Wa;mBWG4iU)v=%qzpmxmIg~zjtDKi042Sx zzjT?R<5^Lws9mz@7+$liW(|dsk1rW}`w?SN=FQA>??F)GhOJzVBEgj~DhRM|VjbZz zd*#w*wmu>l*q}X;c2~Px3BVHZf^CHyRTMjp3vywA{nF3 zfv@YR$)3>rLRonfoGj|@=quD2)qXTsL{7h|QMTKIGEcK-V}?&^!nXTTbvuX0BOre{ z-xSMLgNsF}dfG;j*z!|`5Jt+-I& zUhR`CBnNcMh|Do0tV0JK9EQMjoY~B5$~xRJmAA(}5Cs9>oX*@u;tn(b!B|y}wS=2Y(4OCJz>5>6{1^ z+v1p(`X>(-wLK&hn{5e2bC6~MTw>(C3MBa^5UTm!=gES^~iZ_uT| ze|i`q6K*T?VzqWy(^x_$?mhdLi3Vd(YnW=#5gwdh9$5|j2bpy#TfOXoNZlKK)^^zd z&G@~h@$ft3H=fG+=J%#AIJtD~GCg4PWji;6hz_?^wUCIGz$AaZ!2|EM zk4%>6b((L0`fTnDi6>YQPJB@7XVK>9mSbD>PqPbxhHvgzTr0V~@j_L)x%`%d`N=e^ z_LapP(fH~m3x^}37r#VVyz~L)`zOUq0lapGomjP#M3f}%2Bmvwi!CdD?$V8hmFizB+ql*5Qz3yGM@K7(K#hTEqwwm;_yFe@{rF3hG%^YFK25W%n*;&!$EQVIP=~9g`k48;M`}|gfM50Hl1&BaRpY5zUQG-3kPFlf2Ifo~6=a==GBVJR^gi`i6NlyxJVDaAIKX7s3q za0-m}5R=(#N04~#5a$`^JSu?*i+HhI7wm^~2$TqytM`xEL9H^E7>%e4MsLC#w%<6vJw5TUN06+Y-lM;x0_!4 z&V{?E;9>C=Z4C*FMD~`dvOOY)Jk)~X(M2ow(hiBwyvN9gj=`}VGqwXPwnDsQLP%x5 zw&}Fca}><^T`PS&Z|cb#meiuD-~%e)YsV82%SbvwF=MR_-?(yvF7pr@kR*Fl6&8}L;!NTOM>FiIlW5?AA`C~=|69a_9=a*5$ne7;k4b(=PHphXMN^h!P+h(;pY5GtmQ=)OlMA= zrZCc|M(+BJTtT{cv_sR(&FTr>@Dr8jy2=?draQ(ffOmt7uy1zx(ZVn!u!4Pg?tWSNm61_NpwcmE zT=v82f%;+Es#6=VI7Y@RykTm?&uPn;9^)K?hGV~WC=5QsBobRGwo6!HuMEVPk4XBb zVhbODtYk9nM$%7ECoX4Z**3jN+WUAaX8{S(WwSgzH-b_~%29%L=s!_RJMnxZ*xq!p zY1;<1*_!@bNjc$&6OD3CE0^-8DW99+;Z#0OT&>J=Nx~8{VnFkvppL!;m5z&Rp3z*L zFx6|_D^x>q)uJ@e_hQ9CXR}MAUGH~AS<+aayl?ja{QchP%xj+)wXO~Y^WYNCMDuL= z;0Nn`llZz`X=oV4eY)F9O9sNjzx#YEX6finY!2ku-kY{eGgp0RL91+{CdDnzyzMJ_ z*82>g=dLNUydl+*a^qv0zzfMt$FAtV!_CC7>Wbj7bPQ!2#`dE)@|x7C)cRM;o3Y(b z<=93+-WYgakmg&(NkSLJiwGTtNbxoc1%9ebUm-o+%z-|~m2%UkbnWet(X16u^?5=X zU|Fq!_@tR3(-R8p6j?RyJ_Qk9ueLCA5DAQwb;`cc^wBB=yHQ=J|A5|}2)Aa1-oWx1 zjVbkUyA>y0?Y#R@NC6f#log?&=*rVGFUJ=Jd3ouoa^ex+kMdNmFdfJWTXnV~fuVkb zrL1JBQ6f#!F~|Y(N^%|j@Z&I+yswJ2Wv9^|tG)`jyQ}I_wJVPvGyd8xC~o%-BEmq_ z^Anl4cmipv`R&%TiNNqpu~Wg!KIuBe&nJSu$y&e z;=SKUdTY5prWu>9Y}CD>ZhZ}8&l8I$9iR1gDL=(i<5e3^0LT4$VzAGYVdf;4->MT;hC! zvIwZot2uKyXd{j`RK6f~C|>SXIw-eg3f+*GmnXQu=yPPOSF6M)t{NL9LHWMX0zO8& zamQ{Whe}%b=IP!yCe(o=l;5bnmC2WTWvHlxtJZpOPmXu&U+8|geYCfQF}akLL;M8` zXyEDmQ$_Aodwl()g^pmuSPD_1b5!e^?FuDO@Ok3|o0RpKwe+fxS+~zA`s5x(xL zXM78*1PDD=xLuC;KFd`2oynet6Yo{>d{=RMu4TocbHfz?U^|H;y%e(2*F&N`-6c>? zo{ks^e|Im^OCtb4UeVtRg}#6x0v$0fI1dGZcg>FkfH)@w0ZS=;u)dcn28+`Q#A8eY z4b0Gi7tpd!0*Ytpk)+=T!;%8PLkRJLf`FC25m40= zj{(9Z;1XbvxwO#tq|6nh1f!4Ea0! z!8^pC8h_`{f#jbi;)V4jdJ?dnUVp6fQ~XbgM4a=#uyY{!CpgKiKeq6K zo@k!~=d{%n1V|$iPB}Z?;Dx(8d2v`DfC~!g}HAs{wQa0n97aNJ+t@eis?x{4s7;Y9zZJKS&|qAE7){Jd|4hf%Io;{NUF2bRtp14rvcE z07;4;X$?^a5a`QPDHuu1hCJX&tWc9mDK|q>R<6y8Ps|ZAV zfcC#}>K}0OKiYs6N!Jq}@QZy@jQ5YbAK`Js9c~>!;9(O-qR>Bb4SkpZPKRqqit`U4 z?hhKmf4isrWFdGu6a7$ljIs+UwG{-E5B6xF(cfAqP*oL3$~Y;Y$Zu6G`uB72!(t9f z_Fv}YkG1}7xBM5*5m3IEe{c46l zl0i8;fnZK>DUhSIECPfALt#>~q-_Nz^`o=?@4Nhmt>XW|WfYXOvTzt2zC zj+B)Dmw&%C(Em#lK;VCj{H6H*CtUvt*I$ajUjqLpyZ#fdzZ8ML1pZHU{jY_K?)PVY z7!T6v-jDP|uS-sDl=L)^+EG_i?eMuE;EQT=80i^lV7xn5=J)0RZyL+G@&X{;$?2hf~{uN7aWvGwfZD1Bol#f4sJD;QROmaJ%DK zm~asqmDJYtZ7=lLS$-1$2N~((KuP+9Gm}1<2^Nh6#lfxBris;HUV{*%*v(U)lo}t? zRtG(za3jlN&29al!fJIMtGC)e1c0eh^c~d~8lz99JN(H2hTU0j)u`sYsWwsnIB&S& zB+I$shKF&o*W4ACy;RXz*jQ%<1XNoB>uXE7Aw19B7hgI!>ES?j{G4{q@JM7o*ZDx! z9Cm%qVrcbCOiLN9h$NhBK1R6c!O$JL3*&LC%^@eOHg7+alQj~`fLR>Bld@QgEiaE^ zI8*TKMpS>NO~{H6m%G@Dm1h?(Vn>@f%`@retUb+F{Ut7NvEb>|niyxK1| zb;mL!ytLnKWVpOPui_A3e&Cqtvom$BSd5Q(m(Isd&T9W^jH-au_*Tghbp*Q|%AqD7 z6339>ko+`NfQ#z+eID%ETcD+x<{LxWw5*Q;uc z^X^6qHC~*@o4B9NMm?iKR5j%xGMxis#>$2Hszn_NxfYw$KlL&Rc zNuMtK1Vaz!1<@CkjLn5q*k&bj+@sbHu3;2CRZRGISTzCIIj?K=5559xe_Ta$Cr|Db z=19tzFE5qv51d721oHVxzhqQx6f+x-_q{*qXM3vp(fYErH1R6%uB+8E=c*}HM?;q{ zB09mu5T3QsA#w{xa3oIQ*Zd*V0B8WHIYa?T*&L7XIW(O0fPiHJ|?0F%l~6nz(h@~bf>hy0dVaiuM3hSWNK;vS8ebIz zB}zk6)zFmG@Cb40Y%y0t8tqT;)$!l}a!4yA>f|zohNtr*nd0)`b7M1=L^O5L&h{e( z8V4js^CuF6lxm2`qOi$gkijAPa48^*%b_zz66rLMO{HY z=Bt*(^Cky}bPNYuexyXLR>h-IQ&LhWDGZ8Ioj?V-TrQPHr_$+UxCdD?SD_W^$O_Gn z_8^^cf+3AqEmdiyN(IpvS13{@Y5hnf<3L@Xj{B0Ux&~5cI@rM!sXC#G3Q}m)owMtE*vX>#d+`SGA=Y-Gi8oS5qmCJh^TB9AC z3?t}3+M`kvF;@jqCqo)#l3EOnO@?n}NKbdKmBx1`=YvQ_Pp{Vw>7>2LjGlIxX)3g5 z$QQm>UXU6RYL)5;rBdeKKFcO{A|wU{8E2Ib@yn@Fg+!U68RknxO1ksi9SsT=Y9W84 z5}t`o1iH6CkQek>E@1ZZzxJHLG|*N|{m(Ul!!g@TK8lA!7irHcY zi)n($=bOtv3LUHzCmB~uM`#HgS`4e%bUK&JWQ$m2FrLXEb3|N-%oMTcK0>h%TMTkK zLz~Gz3jMWO3RgOz%&d>`>i_BxJ%ssas8Fc}o}Y8g<}EyXO|@(aH0Q(CPKQits!1xL zS_2tZoFA!k$#oU6t{P?3m{u-NC^l9zf3a~vKoVc-2d&+g)urr^Nk2~Dr%`T?Zzk`3 zjFd!3fwrL9Lz#N@9z>&z*QN;7P+$T)Cwf`yEc3PA9`!>RGQ2OM(RQEt%>PKzebEdt2w6TuLl1%-5=rs641&zNQQgb&_8iOu1 zcO#|U%1DJ&>rd|(4bg0-GCu9JZ^cvK2Xn}u&0;a&m5yviDke&GkSsb_3h$X3<4yq5 z;Jwf!LV9{s#`LN*^K>ZNlV$c0ZK|K`t?(l{{O^F;_4nYT(%Q8H{hcS>xAb>LMa04e zK>$HFFzw@M5?SK+sJL7djt=7sG`Bf^K5C(D@*|7%l`5bQ8mc z&IjSea3O%8n;0&1J_s*{3jqY(#BibWL3lA-2q5Sth6|k!!i(WT06{k~TkLg$0}M&`k^%Iv<1=!-W8XZeqC5`5?R)E(8#C6T^kh2jRtVA%LKp7%p@^ z2rq^U0R-K|aG~=-crjcEAm}EB3!M+bi{U~5K{qj6=zI`f3>N|jx{2XJ=Y#NKxDY_l zO$--0AA}dfg#dzXqT(WSzip9PSZ@sr4vf&%J>4pmIY&BWc$8*1FSlm8yS6SBjVY)t zdpqY;aDhc+Kdbz*Op@o9Wep3L69s(|iO$*I>>@5F@o9Nq)r;=C7Y^N27QCX_!<9CC zeBns>tGD1$+w9lz&v-9Sri820FO+I7y}NUM%e;%#z{)lyA<;sD;f&PN@Bp1cQ?QJA{p7(tFmzQnh zMi|~UI=l_t-NwV`1^L-lT*go6FL+iOC~o`Nen*m}k1fq7_G;cAQo}fxnxS@jy!@JaaU)ryE@C68jSL+LppWVU!H#jPihDeCar=n-xhJ%Xc2crC-@n zBU)JteZgoUhtsstNNX?l|DP{_)_s$fJdS95x zIeo{#%V}muS?FWe5b94ZT3b-1n>XUp)rf7B1VIqFZSq`PbIeOtOxyzJ4Uwnk8r=In z_4F8aKmJhpPomHG?3ytP_gY5TWL(Cl;ZIoYn>gsPOtAOZ;ptt2vcjeDBqsB@%4e^{!L7oTdXePjPvlJm9TT?X|to9pgpV}IIx zXEu#m@!Bf>m~~8`+mUH|oCL1!sf+lL79;kKyAS;SzIOd%zGZ&o1MP|zxbvRWs|8<- zDjst*eSP1f>7_feCQZZZWiA(s1`l70yY}5o!z)Lco*=ljXcrxy$+u?xOx&RhbT*XO zzK;(-+~}~E+Iskrz$FSda`SJ?qexdg-HL|DBU|s3gb8MCBs5+JWmg7F7!}4(^QtTv z){hpO(`22JBvCY+Ew)(#Bv=dyjeWubrds|IF;p1pIhJ$!p@QeVU>~@>V&J^RmYF%B z$Ck1!l@|GXJRf_w$1EK1Q+-tb?dMxW7XtlefrEoW>+W8#oDo&)ZbU)k(NT74ZjVr=QNr1-4Dey)<#njre8W z(@zeHTe>5;uzq@yCq6%aZSI3Zw-d9+KOTNA>>SJb=sy=-(f9ddZJO6_OUkRK&#R0H zzdY>Fpm!e6ce^zn^~%NNwQRVB_uoL3dJjDKit}{d&AT&-zOPwjo7b}Ix4GrlH%qO#bs|H^!xJvGfI>eoB=-Ytvvt$uaVAogsj3_2Uw zFuQ><&LErSihtr0+0-CiUGIE6^6G+r(8k?9yW3*}e%TIgw0@PM&|%ei+Zu{sNSJrC zBYnW?ls6}124~e5I)oGY6a`f^QpPTD44z?6>APB1w`|v`hqrM7?+Q-rJ>?Se;My4W z#`22tSx%QFqrzU)Rc$En-NgLbYxhoRQPzb)0ZD5gWW`;-vQ(CJ$G-lnRWZ*d+f4gM z#B1d0+R62-)(8U z1vXh6$i+pu>nq6iw{7EG&V19dO^{^aD9&7OeLmy`@EFhh@rKRa)74hzT=foX3buZ; z(^b diff --git a/src/qt/res/images/splash.png b/src/qt/res/images/splash.png index 9ebe093cc72dd46fc0f446905822ccfe8eeec860..dc196cc2661fcb4f86de0d6e714b8617a7592a46 100644 GIT binary patch delta 25436 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 G*Z&Uz)oRWF From dca1a02723fb1bd63fcd4a73dd063b79f39b66ae Mon Sep 17 00:00:00 2001 From: Michael Bos Date: Thu, 12 Mar 2020 10:23:16 +0100 Subject: [PATCH 3/4] Updated sources --- src/secp256k1/.gitignore | 2 - src/secp256k1/.travis.yml | 9 +- src/secp256k1/Makefile.am | 34 +- src/secp256k1/README.md | 8 +- .../build-aux/m4/ax_jni_include_dir.m4 | 47 +- src/secp256k1/build-aux/m4/bitcoin_secp.m4 | 1 + src/secp256k1/configure.ac | 52 +- src/secp256k1/contrib/lax_der_parsing.h | 10 +- .../contrib/lax_der_privatekey_parsing.h | 10 +- src/secp256k1/include/secp256k1.h | 97 +-- src/secp256k1/include/secp256k1_ecdh.h | 16 +- src/secp256k1/include/secp256k1_recovery.h | 16 +- src/secp256k1/sage/group_prover.sage | 4 +- src/secp256k1/src/asm/field_10x26_arm.s | 4 +- src/secp256k1/src/basic-config.h | 9 +- src/secp256k1/src/bench.h | 24 +- src/secp256k1/src/bench_ecdh.c | 8 +- src/secp256k1/src/bench_internal.c | 77 +- src/secp256k1/src/bench_recover.c | 8 +- src/secp256k1/src/bench_sign.c | 12 +- src/secp256k1/src/ecdsa.h | 6 +- src/secp256k1/src/ecdsa_impl.h | 36 +- src/secp256k1/src/eckey.h | 6 +- src/secp256k1/src/eckey_impl.h | 17 +- src/secp256k1/src/ecmult.h | 24 +- src/secp256k1/src/ecmult_const.h | 6 +- src/secp256k1/src/ecmult_const_impl.h | 22 +- src/secp256k1/src/ecmult_gen.h | 6 +- src/secp256k1/src/ecmult_gen_impl.h | 8 +- src/secp256k1/src/ecmult_impl.h | 748 ++---------------- src/secp256k1/src/field.h | 11 +- src/secp256k1/src/field_10x26.h | 7 +- src/secp256k1/src/field_10x26_impl.h | 75 +- src/secp256k1/src/field_5x52.h | 6 +- src/secp256k1/src/field_5x52_asm_impl.h | 6 +- src/secp256k1/src/field_5x52_impl.h | 97 +-- src/secp256k1/src/field_5x52_int128_impl.h | 6 +- src/secp256k1/src/field_impl.h | 6 +- src/secp256k1/src/gen_context.c | 2 +- src/secp256k1/src/group.h | 9 +- src/secp256k1/src/group_impl.h | 74 +- src/secp256k1/src/hash.h | 32 +- src/secp256k1/src/hash_impl.h | 55 +- .../src/java/org/bitcoin/NativeSecp256k1.java | 34 +- .../java/org/bitcoin/NativeSecp256k1Test.java | 21 + .../src/java/org_bitcoin_NativeSecp256k1.c | 34 + .../src/java/org_bitcoin_NativeSecp256k1.h | 8 + src/secp256k1/src/modules/ecdh/main_impl.h | 10 +- src/secp256k1/src/modules/ecdh/tests_impl.h | 38 +- .../src/modules/recovery/main_impl.h | 8 +- .../src/modules/recovery/tests_impl.h | 149 +--- src/secp256k1/src/num.h | 6 +- src/secp256k1/src/num_gmp.h | 6 +- src/secp256k1/src/num_gmp_impl.h | 6 +- src/secp256k1/src/num_impl.h | 6 +- src/secp256k1/src/scalar.h | 10 +- src/secp256k1/src/scalar_4x64.h | 6 +- src/secp256k1/src/scalar_4x64_impl.h | 6 +- src/secp256k1/src/scalar_8x32.h | 6 +- src/secp256k1/src/scalar_8x32_impl.h | 6 +- src/secp256k1/src/scalar_impl.h | 216 ++--- src/secp256k1/src/secp256k1.c | 68 +- src/secp256k1/src/testrand.h | 6 +- src/secp256k1/src/testrand_impl.h | 8 +- src/secp256k1/src/tests.c | 551 +------------ src/secp256k1/src/util.h | 19 +- 66 files changed, 724 insertions(+), 2217 deletions(-) diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore index 55d325ae..efb277d3 100644 --- a/src/secp256k1/.gitignore +++ b/src/secp256k1/.gitignore @@ -1,13 +1,11 @@ bench_inv bench_ecdh -bench_ecmult bench_sign bench_verify bench_schnorr_verify bench_recover bench_internal tests -exhaustive_tests gen_context *.exe *.so diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml index c4154e9a..2c5c63ad 100644 --- a/src/secp256k1/.travis.yml +++ b/src/secp256k1/.travis.yml @@ -11,7 +11,7 @@ cache: - src/java/guava/ env: global: - - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=no RECOVERY=no EXPERIMENTAL=no - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar matrix: - SCALAR=32bit RECOVERY=yes @@ -22,14 +22,15 @@ env: - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - FIELD=64bit ASM=x86_64 - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 + - FIELD=32bit SCHNORR=yes EXPERIMENTAL=yes - FIELD=32bit ENDOMORPHISM=yes - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes + - BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes EXPERIMENTAL=yes - BIGNUM=no STATICPRECOMPUTATION=no - BUILD=distcheck - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - EXTRAFLAGS=CFLAGS=-O0 - - BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes + - BUILD=check-java ECDH=yes SCHNORR=yes EXPERIMENTAL=yes matrix: fast_finish: true include: @@ -65,5 +66,5 @@ before_script: ./autogen.sh script: - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD os: linux diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index 01fd0cd6..3d130bdc 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -12,11 +12,9 @@ noinst_HEADERS = noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h noinst_HEADERS += src/scalar_8x32.h -noinst_HEADERS += src/scalar_low.h noinst_HEADERS += src/scalar_impl.h noinst_HEADERS += src/scalar_4x64_impl.h noinst_HEADERS += src/scalar_8x32_impl.h -noinst_HEADERS += src/scalar_low_impl.h noinst_HEADERS += src/group.h noinst_HEADERS += src/group_impl.h noinst_HEADERS += src/num_gmp.h @@ -42,8 +40,6 @@ noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/util.h -noinst_HEADERS += src/scratch.h -noinst_HEADERS += src/scratch_impl.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h noinst_HEADERS += src/hash.h @@ -81,7 +77,7 @@ libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) noinst_PROGRAMS = if USE_BENCHMARK -noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult +noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_verify_SOURCES = src/bench_verify.c bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_sign_SOURCES = src/bench_sign.c @@ -89,34 +85,15 @@ bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) -bench_ecmult_SOURCES = src/bench_ecmult.c -bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) -bench_ecmult_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) endif -TESTS = if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -if !ENABLE_COVERAGE -tests_CPPFLAGS += -DVERIFY -endif +tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static -TESTS += tests -endif - -if USE_EXHAUSTIVE_TESTS -noinst_PROGRAMS += exhaustive_tests -exhaustive_tests_SOURCES = src/tests_exhaustive.c -exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) -if !ENABLE_COVERAGE -exhaustive_tests_CPPFLAGS += -DVERIFY -endif -exhaustive_tests_LDADD = $(SECP_LIBS) -exhaustive_tests_LDFLAGS = -static -TESTS += exhaustive_tests +TESTS = tests endif JAVAROOT=src/java @@ -164,7 +141,6 @@ $(gen_context_BIN): $(gen_context_OBJECTS) $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h $(bench_internal_OBJECTS): src/ecmult_static_context.h -$(bench_ecmult_OBJECTS): src/ecmult_static_context.h src/ecmult_static_context.h: $(gen_context_BIN) ./$(gen_context_BIN) @@ -178,6 +154,10 @@ if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include endif +if ENABLE_MODULE_SCHNORR +include src/modules/schnorr/Makefile.am.include +endif + if ENABLE_MODULE_RECOVERY include src/modules/recovery/Makefile.am.include endif diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md index 9fb25168..c8b65172 100644 --- a/src/secp256k1/README.md +++ b/src/secp256k1/README.md @@ -55,7 +55,13 @@ Build steps libsecp256k1 is built using autotools: $ ./autogen.sh - $ ./configure --enable-module-recovery + $ ./configure $ make $ ./tests $ sudo make install # optional + +$ ./autogen.sh +$ ./configure --enable-module-ecdh --enable-module-schnorr --enable-module-recovery +$ make +$ ./tests +$ sudo make install \ No newline at end of file diff --git a/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 b/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 index cdc78d87..1fc36276 100644 --- a/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 +++ b/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html # =========================================================================== # # SYNOPSIS @@ -44,7 +44,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 14 +#serial 10 AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) AC_DEFUN([AX_JNI_INCLUDE_DIR],[ @@ -66,17 +66,9 @@ else fi case "$host_os" in - darwin*) # Apple Java headers are inside the Xcode bundle. - macos_version=$(sw_vers -productVersion | sed -n -e 's/^@<:@0-9@:>@*.\(@<:@0-9@:>@*\).@<:@0-9@:>@*/\1/p') - if @<:@ "$macos_version" -gt "7" @:>@; then - _JTOPDIR="$(xcrun --show-sdk-path)/System/Library/Frameworks/JavaVM.framework" - _JINC="$_JTOPDIR/Headers" - else - _JTOPDIR="/System/Library/Frameworks/JavaVM.framework" - _JINC="$_JTOPDIR/Headers" - fi - ;; - *) _JINC="$_JTOPDIR/include";; + darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + _JINC="$_JTOPDIR/Headers";; + *) _JINC="$_JTOPDIR/include";; esac _AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) _AS_ECHO_LOG([_JINC=$_JINC]) @@ -84,27 +76,30 @@ _AS_ECHO_LOG([_JINC=$_JINC]) # On Mac OS X 10.6.4, jni.h is a symlink: # /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h # -> ../../CurrentJDK/Headers/jni.h. + AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, [ - if test -f "$_JINC/jni.h"; then - ac_cv_jni_header_path="$_JINC" +if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" +else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" else - _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - if test -f "$_JTOPDIR/include/jni.h"; then - ac_cv_jni_header_path="$_JTOPDIR/include" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" - else - ac_cv_jni_header_path=none - fi + ac_cv_jni_header_path=none fi +fi ]) + + # get the likely subdirectories for system specific java includes case "$host_os" in bsdi*) _JNI_INC_SUBDIRS="bsdos";; -freebsd*) _JNI_INC_SUBDIRS="freebsd";; darwin*) _JNI_INC_SUBDIRS="darwin";; +freebsd*) _JNI_INC_SUBDIRS="freebsd";; linux*) _JNI_INC_SUBDIRS="linux genunix";; osf*) _JNI_INC_SUBDIRS="alpha";; solaris*) _JNI_INC_SUBDIRS="solaris";; @@ -117,9 +112,9 @@ if test "x$ac_cv_jni_header_path" != "xnone"; then # add any subdirectories that are present for JINCSUBDIR in $_JNI_INC_SUBDIRS do - if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" - fi + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi done fi ]) diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 index 3b3975cb..b74acb8c 100644 --- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 +++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 @@ -48,6 +48,7 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then EC_KEY_free(eckey); ECDSA_SIG *sig_openssl; sig_openssl = ECDSA_SIG_new(); + (void)sig_openssl->r; ECDSA_SIG_free(sig_openssl); ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) AC_MSG_RESULT([$has_openssl_ec]) diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac index 68c45a56..67a9d460 100644 --- a/src/secp256k1/configure.ac +++ b/src/secp256k1/configure.ac @@ -20,7 +20,7 @@ AC_PATH_TOOL(STRIP, strip) AX_PROG_CC_FOR_BUILD if test "x$CFLAGS" = "x"; then - CFLAGS="-g" + CFLAGS="-O3 -g" fi AM_PROG_CC_C_O @@ -85,14 +85,9 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], ]) AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]), + AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), [use_benchmark=$enableval], - [use_benchmark=yes]) - -AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), - [enable_coverage=$enableval], - [enable_coverage=no]) + [use_benchmark=no]) AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), @@ -109,11 +104,6 @@ AC_ARG_ENABLE(experimental, [use_experimental=$enableval], [use_experimental=no]) -AC_ARG_ENABLE(exhaustive_tests, - AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), - [use_exhaustive_tests=$enableval], - [use_exhaustive_tests=yes]) - AC_ARG_ENABLE(endomorphism, AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), [use_endomorphism=$enableval], @@ -129,15 +119,20 @@ AC_ARG_ENABLE(module_ecdh, [enable_module_ecdh=$enableval], [enable_module_ecdh=no]) +AC_ARG_ENABLE(module_schnorr, + AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (experimental)]), + [enable_module_schnorr=$enableval], + [enable_module_schnorr=no]) + AC_ARG_ENABLE(module_recovery, AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), [enable_module_recovery=$enableval], [enable_module_recovery=no]) AC_ARG_ENABLE(jni, - AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is no)]), + AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), [use_jni=$enableval], - [use_jni=no]) + [use_jni=auto]) AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) @@ -159,14 +154,6 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], [ AC_MSG_RESULT([no]) ]) -if test x"$enable_coverage" = x"yes"; then - AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) - CFLAGS="$CFLAGS -O0 --coverage" - LDFLAGS="--coverage" -else - CFLAGS="$CFLAGS -O3" -fi - if test x"$use_ecmult_static_precomputation" != x"no"; then save_cross_compiling=$cross_compiling cross_compiling=no @@ -394,6 +381,9 @@ fi if test x"$use_jni" != x"no"; then AX_JNI_INCLUDE_DIR have_jni_dependencies=yes + if test x"$enable_module_schnorr" = x"no"; then + have_jni_dependencies=no + fi if test x"$enable_module_ecdh" = x"no"; then have_jni_dependencies=no fi @@ -402,7 +392,7 @@ if test x"$use_jni" != x"no"; then fi if test "x$have_jni_dependencies" = "xno"; then if test x"$use_jni" = x"yes"; then - AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and Schnorr and try again.]) fi AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) use_jni=no @@ -431,6 +421,10 @@ if test x"$enable_module_ecdh" = x"yes"; then AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) fi +if test x"$enable_module_schnorr" = x"yes"; then + AC_DEFINE(ENABLE_MODULE_SCHNORR, 1, [Define this symbol to enable the Schnorr signature module]) +fi + if test x"$enable_module_recovery" = x"yes"; then AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) fi @@ -447,9 +441,8 @@ AC_MSG_NOTICE([Using field implementation: $set_field]) AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) -AC_MSG_NOTICE([Building benchmarks: $use_benchmark]) -AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) +AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) AC_MSG_NOTICE([Using jni: $use_jni]) @@ -458,8 +451,12 @@ if test x"$enable_experimental" = x"yes"; then AC_MSG_NOTICE([WARNING: experimental build]) AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) + AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([******]) else + if test x"$enable_module_schnorr" = x"yes"; then + AC_MSG_ERROR([Schnorr signature module is experimental. Use --enable-experimental to allow.]) + fi if test x"$enable_module_ecdh" = x"yes"; then AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) fi @@ -475,12 +472,11 @@ AC_SUBST(SECP_INCLUDES) AC_SUBST(SECP_LIBS) AC_SUBST(SECP_TEST_LIBS) AC_SUBST(SECP_TEST_INCLUDES) -AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) -AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h index 7eaf63bf..6d27871a 100644 --- a/src/secp256k1/contrib/lax_der_parsing.h +++ b/src/secp256k1/contrib/lax_der_parsing.h @@ -48,14 +48,14 @@ * 8.3.1. */ -#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H -#define SECP256K1_CONTRIB_LAX_DER_PARSING_H +#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ #include -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /** Parse a signature in "lax DER" format * @@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax( } #endif -#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ +#endif diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h index fece261f..2fd088f8 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -25,14 +25,14 @@ * library are sufficient. */ -#ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H -#define SECP256K1_CONTRIB_BER_PRIVATEKEY_H +#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ +#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ #include -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /** Export a private key in DER format. * @@ -87,4 +87,4 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( } #endif -#endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ +#endif diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h index 5c109f48..f268e309 100644 --- a/src/secp256k1/include/secp256k1.h +++ b/src/secp256k1/include/secp256k1.h @@ -1,9 +1,9 @@ -#ifndef SECP256K1_H -#define SECP256K1_H +#ifndef _SECP256K1_ +# define _SECP256K1_ -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif #include @@ -42,19 +42,6 @@ extern "C" { */ typedef struct secp256k1_context_struct secp256k1_context; -/** Opaque data structure that holds rewriteable "scratch space" - * - * The purpose of this structure is to replace dynamic memory allocations, - * because we target architectures where this may not be available. It is - * essentially a resizable (within specified parameters) block of bytes, - * which is initially created either by memory allocation or TODO as a pointer - * into some fixed rewritable space. - * - * Unlike the context object, this cannot safely be shared between threads - * without additional synchronization logic. - */ -typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; - /** Opaque data structure that holds a parsed and valid public key. * * The exact representation of data inside is implementation defined and not @@ -74,7 +61,7 @@ typedef struct { * however guaranteed to be 64 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage, transmission, or * comparison, use the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. + * secp256k1_ecdsa_signature_serialize_* functions. */ typedef struct { unsigned char data[64]; @@ -172,19 +159,10 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) -/** Prefix byte used to tag various encoded curvepoints for specific purposes */ -#define SECP256K1_TAG_PUBKEY_EVEN 0x02 -#define SECP256K1_TAG_PUBKEY_ODD 0x03 -#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 -#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 -#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 - /** Create a secp256k1 context object. * * Returns: a newly created context object. * In: flags: which parts of the context to initialize. - * - * See also secp256k1_context_randomize. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags @@ -256,28 +234,6 @@ SECP256K1_API void secp256k1_context_set_error_callback( const void* data ) SECP256K1_ARG_NONNULL(1); -/** Create a secp256k1 scratch space object. - * - * Returns: a newly created scratch space. - * Args: ctx: an existing context object (cannot be NULL) - * In: init_size: initial amount of memory to allocate - * max_size: maximum amount of memory to allocate - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create( - const secp256k1_context* ctx, - size_t init_size, - size_t max_size -) SECP256K1_ARG_NONNULL(1); - -/** Destroy a secp256k1 scratch space. - * - * The pointer may not be used afterwards. - * Args: scratch: space to destroy - */ -SECP256K1_API void secp256k1_scratch_space_destroy( - secp256k1_scratch_space* scratch -); - /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. @@ -529,28 +485,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Negates a private key in place. - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( - const secp256k1_context* ctx, - unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Negates a public key in place. - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - /** Tweak a private key by adding tweak to it. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or if the resulting private key @@ -609,24 +543,11 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization to protect against side-channel leakage. +/** Updates the context randomization. * Returns: 1: randomization successfully updated * 0: error * Args: ctx: pointer to a context object (cannot be NULL) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) - * - * While secp256k1 code is written to be constant-time no matter what secret - * values are, it's possible that a future compiler may output code which isn't, - * and also that the CPU may not emit the same radio frequencies or draw the same - * amount power for all values. - * - * This function provides a seed which is combined into the blinding value: that - * blinding value is added before each multiplication (and removed afterwards) so - * that it does not affect function results, but shields against attacks which - * rely on any input-dependent behaviour. - * - * You should call this after secp256k1_context_create or - * secp256k1_context_clone, and may call this repeatedly afterwards. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( secp256k1_context* ctx, @@ -649,8 +570,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( size_t n ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif -#endif /* SECP256K1_H */ +#endif diff --git a/src/secp256k1/include/secp256k1_ecdh.h b/src/secp256k1/include/secp256k1_ecdh.h index 88492dc1..4b84d7a9 100644 --- a/src/secp256k1/include/secp256k1_ecdh.h +++ b/src/secp256k1/include/secp256k1_ecdh.h @@ -1,11 +1,11 @@ -#ifndef SECP256K1_ECDH_H -#define SECP256K1_ECDH_H +#ifndef _SECP256K1_ECDH_ +# define _SECP256K1_ECDH_ -#include "secp256k1.h" +# include "secp256k1.h" -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /** Compute an EC Diffie-Hellman secret in constant time * Returns: 1: exponentiation was successful @@ -24,8 +24,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( const unsigned char *privkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif -#endif /* SECP256K1_ECDH_H */ +#endif diff --git a/src/secp256k1/include/secp256k1_recovery.h b/src/secp256k1/include/secp256k1_recovery.h index cf6c5ed7..05537972 100644 --- a/src/secp256k1/include/secp256k1_recovery.h +++ b/src/secp256k1/include/secp256k1_recovery.h @@ -1,11 +1,11 @@ -#ifndef SECP256K1_RECOVERY_H -#define SECP256K1_RECOVERY_H +#ifndef _SECP256K1_RECOVERY_ +# define _SECP256K1_RECOVERY_ -#include "secp256k1.h" +# include "secp256k1.h" -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif /** Opaque data structured that holds a parsed ECDSA signature, * supporting pubkey recovery. @@ -103,8 +103,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( const unsigned char *msg32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif -#endif /* SECP256K1_RECOVERY_H */ +#endif diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage index 8521f079..ab580c5b 100644 --- a/src/secp256k1/sage/group_prover.sage +++ b/src/secp256k1/sage/group_prover.sage @@ -3,7 +3,7 @@ # to independently set assumptions on input or intermediary variables. # # The general approach is: -# * A constraint is a tuple of two sets of symbolic expressions: +# * A constraint is a tuple of two sets of of symbolic expressions: # the first of which are required to evaluate to zero, the second of which # are required to evaluate to nonzero. # - A constraint is said to be conflicting if any of its nonzero expressions @@ -17,7 +17,7 @@ # - A constraint describing the requirements of the law, called "require" # * Implementations are transliterated into functions that operate as well on # algebraic input points, and are called once per combination of branches -# executed. Each execution returns: +# exectured. Each execution returns: # - A constraint describing the assumptions this implementation requires # (such as Z1=1), called "assumeFormula" # - A constraint describing the assumptions this specific branch requires, diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s index 5a9cc3ff..5df561f2 100644 --- a/src/secp256k1/src/asm/field_10x26_arm.s +++ b/src/secp256k1/src/asm/field_10x26_arm.s @@ -11,7 +11,7 @@ Note: - To avoid unnecessary loads and make use of available registers, two 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the even passes + which will be added to c and d respectively in the the even passes */ @@ -23,7 +23,7 @@ Note: .eabi_attribute 10, 0 @ Tag_FP_arch = none .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP - .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed + .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 .text diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h index fc588061..c4c16eb7 100644 --- a/src/secp256k1/src/basic-config.h +++ b/src/secp256k1/src/basic-config.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_BASIC_CONFIG_H -#define SECP256K1_BASIC_CONFIG_H +#ifndef _SECP256K1_BASIC_CONFIG_ +#define _SECP256K1_BASIC_CONFIG_ #ifdef USE_BASIC_CONFIG @@ -28,6 +28,5 @@ #define USE_FIELD_10X26 1 #define USE_SCALAR_8X32 1 -#endif /* USE_BASIC_CONFIG */ - -#endif /* SECP256K1_BASIC_CONFIG_H */ +#endif // USE_BASIC_CONFIG +#endif // _SECP256K1_BASIC_CONFIG_ diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index 5b59783f..3a71b4aa 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -4,11 +4,10 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_BENCH_H -#define SECP256K1_BENCH_H +#ifndef _SECP256K1_BENCH_H_ +#define _SECP256K1_BENCH_H_ #include -#include #include #include "sys/time.h" @@ -24,7 +23,7 @@ void print_number(double x) { if (y < 0.0) { y = -y; } - while (y > 0 && y < 100.0) { + while (y < 100.0) { y *= 10.0; c++; } @@ -64,19 +63,4 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v printf("us\n"); } -int have_flag(int argc, char** argv, char *flag) { - char** argm = argv + argc; - argv++; - if (argv == argm) { - return 1; - } - while (argv != NULL && argv != argm) { - if (strcmp(*argv, flag) == 0) { - return 1; - } - argv++; - } - return 0; -} - -#endif /* SECP256K1_BENCH_H */ +#endif diff --git a/src/secp256k1/src/bench_ecdh.c b/src/secp256k1/src/bench_ecdh.c index 5837f4e7..cde5e2db 100644 --- a/src/secp256k1/src/bench_ecdh.c +++ b/src/secp256k1/src/bench_ecdh.c @@ -15,11 +15,11 @@ typedef struct { secp256k1_context *ctx; secp256k1_pubkey point; unsigned char scalar[32]; -} bench_ecdh_data; +} bench_ecdh_t; static void bench_ecdh_setup(void* arg) { int i; - bench_ecdh_data *data = (bench_ecdh_data*)arg; + bench_ecdh_t *data = (bench_ecdh_t*)arg; const unsigned char point[] = { 0x03, 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, @@ -39,7 +39,7 @@ static void bench_ecdh_setup(void* arg) { static void bench_ecdh(void* arg) { int i; unsigned char res[32]; - bench_ecdh_data *data = (bench_ecdh_data*)arg; + bench_ecdh_t *data = (bench_ecdh_t*)arg; for (i = 0; i < 20000; i++) { CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); @@ -47,7 +47,7 @@ static void bench_ecdh(void* arg) { } int main(void) { - bench_ecdh_data data; + bench_ecdh_t data; run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); return 0; diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c index 996aa8b0..0809f77b 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -25,10 +25,10 @@ typedef struct { secp256k1_gej gej_x, gej_y; unsigned char data[64]; int wnaf[256]; -} bench_inv; +} bench_inv_t; void bench_setup(void* arg) { - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; static const unsigned char init_x[32] = { 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, @@ -58,7 +58,7 @@ void bench_setup(void* arg) { void bench_scalar_add(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); @@ -67,7 +67,7 @@ void bench_scalar_add(void* arg) { void bench_scalar_negate(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); @@ -76,7 +76,7 @@ void bench_scalar_negate(void* arg) { void bench_scalar_sqr(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); @@ -85,7 +85,7 @@ void bench_scalar_sqr(void* arg) { void bench_scalar_mul(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); @@ -95,7 +95,7 @@ void bench_scalar_mul(void* arg) { #ifdef USE_ENDOMORPHISM void bench_scalar_split(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_scalar l, r; @@ -107,7 +107,7 @@ void bench_scalar_split(void* arg) { void bench_scalar_inverse(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); @@ -117,7 +117,7 @@ void bench_scalar_inverse(void* arg) { void bench_scalar_inverse_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); @@ -127,7 +127,7 @@ void bench_scalar_inverse_var(void* arg) { void bench_field_normalize(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize(&data->fe_x); @@ -136,7 +136,7 @@ void bench_field_normalize(void* arg) { void bench_field_normalize_weak(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize_weak(&data->fe_x); @@ -145,7 +145,7 @@ void bench_field_normalize_weak(void* arg) { void bench_field_mul(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); @@ -154,7 +154,7 @@ void bench_field_mul(void* arg) { void bench_field_sqr(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_sqr(&data->fe_x, &data->fe_x); @@ -163,7 +163,7 @@ void bench_field_sqr(void* arg) { void bench_field_inverse(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv(&data->fe_x, &data->fe_x); @@ -173,7 +173,7 @@ void bench_field_inverse(void* arg) { void bench_field_inverse_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); @@ -183,7 +183,7 @@ void bench_field_inverse_var(void* arg) { void bench_field_sqrt(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); @@ -193,7 +193,7 @@ void bench_field_sqrt(void* arg) { void bench_group_double_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); @@ -202,7 +202,7 @@ void bench_group_double_var(void* arg) { void bench_group_add_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); @@ -211,7 +211,7 @@ void bench_group_add_var(void* arg) { void bench_group_add_affine(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); @@ -220,7 +220,7 @@ void bench_group_add_affine(void* arg) { void bench_group_add_affine_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); @@ -229,7 +229,7 @@ void bench_group_add_affine_var(void* arg) { void bench_group_jacobi_var(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_gej_has_quad_y_var(&data->gej_x); @@ -238,7 +238,7 @@ void bench_group_jacobi_var(void* arg) { void bench_ecmult_wnaf(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); @@ -248,7 +248,7 @@ void bench_ecmult_wnaf(void* arg) { void bench_wnaf_const(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; for (i = 0; i < 20000; i++) { secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); @@ -259,8 +259,8 @@ void bench_wnaf_const(void* arg) { void bench_sha256(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_sha256 sha; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_sha256_t sha; for (i = 0; i < 20000; i++) { secp256k1_sha256_initialize(&sha); @@ -271,8 +271,8 @@ void bench_sha256(void* arg) { void bench_hmac_sha256(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_hmac_sha256 hmac; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_hmac_sha256_t hmac; for (i = 0; i < 20000; i++) { secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); @@ -283,8 +283,8 @@ void bench_hmac_sha256(void* arg) { void bench_rfc6979_hmac_sha256(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_rfc6979_hmac_sha256 rng; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_rfc6979_hmac_sha256_t rng; for (i = 0; i < 20000; i++) { secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); @@ -311,7 +311,7 @@ void bench_context_sign(void* arg) { #ifndef USE_NUM_NONE void bench_num_jacobi(void* arg) { int i; - bench_inv *data = (bench_inv*)arg; + bench_inv_t *data = (bench_inv_t*)arg; secp256k1_num nx, norder; secp256k1_scalar_get_num(&nx, &data->scalar_x); @@ -324,8 +324,23 @@ void bench_num_jacobi(void* arg) { } #endif +int have_flag(int argc, char** argv, char *flag) { + char** argm = argv + argc; + argv++; + if (argv == argm) { + return 1; + } + while (argv != NULL && argv != argm) { + if (strcmp(*argv, flag) == 0) { + return 1; + } + argv++; + } + return 0; +} + int main(int argc, char **argv) { - bench_inv data; + bench_inv_t data; if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c index b806eed9..6489378c 100644 --- a/src/secp256k1/src/bench_recover.c +++ b/src/secp256k1/src/bench_recover.c @@ -13,11 +13,11 @@ typedef struct { secp256k1_context *ctx; unsigned char msg[32]; unsigned char sig[64]; -} bench_recover_data; +} bench_recover_t; void bench_recover(void* arg) { int i; - bench_recover_data *data = (bench_recover_data*)arg; + bench_recover_t *data = (bench_recover_t*)arg; secp256k1_pubkey pubkey; unsigned char pubkeyc[33]; @@ -38,7 +38,7 @@ void bench_recover(void* arg) { void bench_recover_setup(void* arg) { int i; - bench_recover_data *data = (bench_recover_data*)arg; + bench_recover_t *data = (bench_recover_t*)arg; for (i = 0; i < 32; i++) { data->msg[i] = 1 + i; @@ -49,7 +49,7 @@ void bench_recover_setup(void* arg) { } int main(void) { - bench_recover_data data; + bench_recover_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c index 544b4396..ed7224d7 100644 --- a/src/secp256k1/src/bench_sign.c +++ b/src/secp256k1/src/bench_sign.c @@ -12,11 +12,11 @@ typedef struct { secp256k1_context* ctx; unsigned char msg[32]; unsigned char key[32]; -} bench_sign; +} bench_sign_t; static void bench_sign_setup(void* arg) { int i; - bench_sign *data = (bench_sign*)arg; + bench_sign_t *data = (bench_sign_t*)arg; for (i = 0; i < 32; i++) { data->msg[i] = i + 1; @@ -26,9 +26,9 @@ static void bench_sign_setup(void* arg) { } } -static void bench_sign_run(void* arg) { +static void bench_sign(void* arg) { int i; - bench_sign *data = (bench_sign*)arg; + bench_sign_t *data = (bench_sign_t*)arg; unsigned char sig[74]; for (i = 0; i < 20000; i++) { @@ -45,11 +45,11 @@ static void bench_sign_run(void* arg) { } int main(void) { - bench_sign data; + bench_sign_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, 20000); + run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); secp256k1_context_destroy(data.ctx); return 0; diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h index 80590c7c..54ae101b 100644 --- a/src/secp256k1/src/ecdsa.h +++ b/src/secp256k1/src/ecdsa.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECDSA_H -#define SECP256K1_ECDSA_H +#ifndef _SECP256K1_ECDSA_ +#define _SECP256K1_ECDSA_ #include @@ -18,4 +18,4 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); -#endif /* SECP256K1_ECDSA_H */ +#endif diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h index c3400042..d110b4bb 100644 --- a/src/secp256k1/src/ecdsa_impl.h +++ b/src/secp256k1/src/ecdsa_impl.h @@ -5,8 +5,8 @@ **********************************************************************/ -#ifndef SECP256K1_ECDSA_IMPL_H -#define SECP256K1_ECDSA_IMPL_H +#ifndef _SECP256K1_ECDSA_IMPL_H_ +#define _SECP256K1_ECDSA_IMPL_H_ #include "scalar.h" #include "field.h" @@ -81,6 +81,8 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha return -1; } while (lenleft > 0) { + if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { + } ret = (ret << 8) | **sigp; if (ret + lenleft > (size_t)(sigend - *sigp)) { /* Result exceeds the length of the passed array. */ @@ -201,9 +203,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { unsigned char c[32]; secp256k1_scalar sn, u1, u2; -#if !defined(EXHAUSTIVE_TEST_ORDER) secp256k1_fe xr; -#endif secp256k1_gej pubkeyj; secp256k1_gej pr; @@ -219,19 +219,6 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const if (secp256k1_gej_is_infinity(&pr)) { return 0; } - -#if defined(EXHAUSTIVE_TEST_ORDER) -{ - secp256k1_scalar computed_r; - secp256k1_ge pr_ge; - secp256k1_ge_set_gej(&pr_ge, &pr); - secp256k1_fe_normalize(&pr_ge.x); - - secp256k1_fe_get_b32(c, &pr_ge.x); - secp256k1_scalar_set_b32(&computed_r, c, NULL); - return secp256k1_scalar_eq(sigr, &computed_r); -} -#else secp256k1_scalar_get_b32(c, sigr); secp256k1_fe_set_b32(&xr, c); @@ -265,7 +252,6 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const return 1; } return 0; -#endif } static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { @@ -281,10 +267,14 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); secp256k1_scalar_set_b32(sigr, b, &overflow); - /* These two conditions should be checked before calling */ - VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); - VERIFY_CHECK(overflow == 0); - + if (secp256k1_scalar_is_zero(sigr)) { + /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. + * This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. + */ + secp256k1_gej_clear(&rp); + secp256k1_ge_clear(&r); + return 0; + } if (recid) { /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. @@ -310,4 +300,4 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec return 1; } -#endif /* SECP256K1_ECDSA_IMPL_H */ +#endif diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h index b621f1e6..42739a3b 100644 --- a/src/secp256k1/src/eckey.h +++ b/src/secp256k1/src/eckey.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECKEY_H -#define SECP256K1_ECKEY_H +#ifndef _SECP256K1_ECKEY_ +#define _SECP256K1_ECKEY_ #include @@ -22,4 +22,4 @@ static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); -#endif /* SECP256K1_ECKEY_H */ +#endif diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h index 1ab9a68e..ce38071a 100644 --- a/src/secp256k1/src/eckey_impl.h +++ b/src/secp256k1/src/eckey_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECKEY_IMPL_H -#define SECP256K1_ECKEY_IMPL_H +#ifndef _SECP256K1_ECKEY_IMPL_H_ +#define _SECP256K1_ECKEY_IMPL_H_ #include "eckey.h" @@ -15,17 +15,16 @@ #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { - if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { secp256k1_fe x; - return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); + return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { secp256k1_fe x, y; if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { return 0; } secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && - secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { + if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { return 0; } return secp256k1_ge_is_valid_var(elem); @@ -43,10 +42,10 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p secp256k1_fe_get_b32(&pub[1], &elem->x); if (compressed) { *size = 33; - pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); } else { *size = 65; - pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; + pub[0] = 0x04; secp256k1_fe_get_b32(&pub[33], &elem->y); } return 1; @@ -97,4 +96,4 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, return 1; } -#endif /* SECP256K1_ECKEY_IMPL_H */ +#endif diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h index ea1cd8a2..20484134 100644 --- a/src/secp256k1/src/ecmult.h +++ b/src/secp256k1/src/ecmult.h @@ -1,16 +1,14 @@ /********************************************************************** - * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * + * Copyright (c) 2013, 2014 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECMULT_H -#define SECP256K1_ECMULT_H +#ifndef _SECP256K1_ECMULT_ +#define _SECP256K1_ECMULT_ #include "num.h" #include "group.h" -#include "scalar.h" -#include "scratch.h" typedef struct { /* For accelerating the computation of a*P + b*G: */ @@ -30,18 +28,4 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx /** Double multiply: R = na*A + ng*G */ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); -typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); - -/** - * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. - * Chooses the right algorithm for a given number of points and scratch space - * size. Resets and overwrites the given scratch space. If the points do not - * fit in the scratch space the algorithm is repeatedly run with batches of - * points. - * Returns: 1 on success (including when inp_g_sc is NULL and n is 0) - * 0 if there is not enough scratch space for a single point or - * callback returns 0 - */ -static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); - -#endif /* SECP256K1_ECMULT_H */ +#endif diff --git a/src/secp256k1/src/ecmult_const.h b/src/secp256k1/src/ecmult_const.h index 72bf7d75..2b009765 100644 --- a/src/secp256k1/src/ecmult_const.h +++ b/src/secp256k1/src/ecmult_const.h @@ -4,12 +4,12 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECMULT_CONST_H -#define SECP256K1_ECMULT_CONST_H +#ifndef _SECP256K1_ECMULT_CONST_ +#define _SECP256K1_ECMULT_CONST_ #include "scalar.h" #include "group.h" static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); -#endif /* SECP256K1_ECMULT_CONST_H */ +#endif diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h index fae50020..7a6a2531 100644 --- a/src/secp256k1/src/ecmult_const_impl.h +++ b/src/secp256k1/src/ecmult_const_impl.h @@ -4,14 +4,21 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECMULT_CONST_IMPL_H -#define SECP256K1_ECMULT_CONST_IMPL_H +#ifndef _SECP256K1_ECMULT_CONST_IMPL_ +#define _SECP256K1_ECMULT_CONST_IMPL_ #include "scalar.h" #include "group.h" #include "ecmult_const.h" #include "ecmult_impl.h" +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) + /* This is like `ECMULT_TABLE_GET_GE` but is constant time */ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ int m; \ @@ -35,12 +42,11 @@ } while(0) -/** Convert a number to WNAF notation. - * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. - * It has the following guarantees: +/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) + * with the following guarantees: * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) * - each wnaf[i] is nonzero - * - the number of words set is always WNAF_SIZE(w) + 1 + * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w * * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) @@ -72,7 +78,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { /* Negative numbers will be negated to keep their bit representation below the maximum width */ flip = secp256k1_scalar_is_high(&s); /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ !secp256k1_scalar_is_even(&s); + bit = flip ^ (s.d[0] & 1); /* We check for negative one, since adding 2 to it will cause an overflow */ secp256k1_scalar_negate(&neg_s, &s); not_neg_one = !secp256k1_scalar_is_one(&neg_s); @@ -230,4 +236,4 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons } } -#endif /* SECP256K1_ECMULT_CONST_IMPL_H */ +#endif diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h index 7564b701..eb2cc9ea 100644 --- a/src/secp256k1/src/ecmult_gen.h +++ b/src/secp256k1/src/ecmult_gen.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECMULT_GEN_H -#define SECP256K1_ECMULT_GEN_H +#ifndef _SECP256K1_ECMULT_GEN_ +#define _SECP256K1_ECMULT_GEN_ #include "scalar.h" #include "group.h" @@ -40,4 +40,4 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp25 static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); -#endif /* SECP256K1_ECMULT_GEN_H */ +#endif diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h index 714f02e9..35f25460 100644 --- a/src/secp256k1/src/ecmult_gen_impl.h +++ b/src/secp256k1/src/ecmult_gen_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_ECMULT_GEN_IMPL_H -#define SECP256K1_ECMULT_GEN_IMPL_H +#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ +#define _SECP256K1_ECMULT_GEN_IMPL_H_ #include "scalar.h" #include "group.h" @@ -161,7 +161,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_gej gb; secp256k1_fe s; unsigned char nonce32[32]; - secp256k1_rfc6979_hmac_sha256 rng; + secp256k1_rfc6979_hmac_sha256_t rng; int retry; unsigned char keydata[64] = {0}; if (seed32 == NULL) { @@ -207,4 +207,4 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_gej_clear(&gb); } -#endif /* SECP256K1_ECMULT_GEN_IMPL_H */ +#endif diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index fd14bf12..d1e83bd6 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1,36 +1,21 @@ -/***************************************************************************** - * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php. * - *****************************************************************************/ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ -#ifndef SECP256K1_ECMULT_IMPL_H -#define SECP256K1_ECMULT_IMPL_H - -#include -#include +#ifndef _SECP256K1_ECMULT_IMPL_H_ +#define _SECP256K1_ECMULT_IMPL_H_ #include "group.h" #include "scalar.h" #include "ecmult.h" -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need to lower these values for exhaustive tests because - * the tables cannot have infinities in them (this breaks the - * affine-isomorphism stuff which tracks z-ratios) */ -# if EXHAUSTIVE_TEST_ORDER > 128 -# define WINDOW_A 5 -# define WINDOW_G 8 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define WINDOW_A 4 -# define WINDOW_G 4 -# else -# define WINDOW_A 2 -# define WINDOW_G 2 -# endif -#else +#include + /* optimal for 128-bit and 256-bit exponents. */ #define WINDOW_A 5 + /** larger numbers may result in slightly better performance, at the cost of exponentially larger precomputed tables. */ #ifdef USE_ENDOMORPHISM @@ -40,37 +25,10 @@ /** One table for window size 16: 1.375 MiB. */ #define WINDOW_G 16 #endif -#endif - -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) /** The number of entries a table with precomputed multiples needs to have. */ #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) -/* The number of objects allocated on the scratch space for ecmult_multi algorithms */ -#define PIPPENGER_SCRATCH_OBJECTS 6 -#define STRAUSS_SCRATCH_OBJECTS 6 - -#define PIPPENGER_MAX_BUCKET_WINDOW 12 - -/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */ -#ifdef USE_ENDOMORPHISM - #define ECMULT_PIPPENGER_THRESHOLD 88 -#else - #define ECMULT_PIPPENGER_THRESHOLD 160 -#endif - -#ifdef USE_ENDOMORPHISM - #define ECMULT_MAX_POINTS_PER_BATCH 5000000 -#else - #define ECMULT_MAX_POINTS_PER_BATCH 10000000 -#endif - /** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. @@ -310,78 +268,50 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, return last_set_bit + 1; } -struct secp256k1_strauss_point_state { +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge tmpa; + secp256k1_fe Z; #ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_scalar na_1, na_lam; + /* Splitted G factors. */ + secp256k1_scalar ng_1, ng_128; int wnaf_na_1[130]; int wnaf_na_lam[130]; int bits_na_1; int bits_na_lam; -#else - int wnaf_na[256]; - int bits_na; -#endif - size_t input_pos; -}; - -struct secp256k1_strauss_state { - secp256k1_gej* prej; - secp256k1_fe* zr; - secp256k1_ge* pre_a; -#ifdef USE_ENDOMORPHISM - secp256k1_ge* pre_a_lam; -#endif - struct secp256k1_strauss_point_state* ps; -}; - -static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge tmpa; - secp256k1_fe Z; -#ifdef USE_ENDOMORPHISM - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; int wnaf_ng_1[129]; - int bits_ng_1 = 0; + int bits_ng_1; int wnaf_ng_128[129]; - int bits_ng_128 = 0; + int bits_ng_128; #else + int wnaf_na[256]; + int bits_na; int wnaf_ng[256]; - int bits_ng = 0; + int bits_ng; #endif int i; - int bits = 0; - int np; - int no = 0; + int bits; - for (np = 0; np < num; ++np) { - if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) { - continue; - } - state->ps[no].input_pos = np; #ifdef USE_ENDOMORPHISM - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]); - - /* build wnaf representation for na_1 and na_lam. */ - state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, WINDOW_A); - state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 130, &state->ps[no].na_lam, WINDOW_A); - VERIFY_CHECK(state->ps[no].bits_na_1 <= 130); - VERIFY_CHECK(state->ps[no].bits_na_lam <= 130); - if (state->ps[no].bits_na_1 > bits) { - bits = state->ps[no].bits_na_1; - } - if (state->ps[no].bits_na_lam > bits) { - bits = state->ps[no].bits_na_lam; - } + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&na_1, &na_lam, na); + + /* build wnaf representation for na_1 and na_lam. */ + bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); + bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); + VERIFY_CHECK(bits_na_1 <= 130); + VERIFY_CHECK(bits_na_lam <= 130); + bits = bits_na_1; + if (bits_na_lam > bits) { + bits = bits_na_lam; + } #else - /* build wnaf representation for na. */ - state->ps[no].bits_na = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A); - if (state->ps[no].bits_na > bits) { - bits = state->ps[no].bits_na; - } + /* build wnaf representation for na. */ + bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); + bits = bits_na; #endif - ++no; - } /* Calculate odd multiples of a. * All multiples are brought to the same Z 'denominator', which is stored @@ -393,51 +323,29 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same * isomorphism to efficiently add with a known Z inverse. */ - if (no > 0) { - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]); - for (np = 1; np < no; ++np) { - secp256k1_gej tmp = a[state->ps[np].input_pos]; -#ifdef VERIFY - secp256k1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); -#endif - secp256k1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &tmp); - secp256k1_fe_mul(state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &(a[state->ps[np].input_pos].z)); - } - /* Bring them to the same Z denominator. */ - secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr); - } else { - secp256k1_fe_set_int(&Z, 1); - } + secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); #ifdef USE_ENDOMORPHISM - for (np = 0; np < no; ++np) { - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]); - } + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); } - if (ng) { - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); + /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; - } + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; } #else - if (ng) { - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; - } + bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; } #endif @@ -447,15 +355,13 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c int n; secp256k1_gej_double_var(r, r, NULL); #ifdef USE_ENDOMORPHISM - for (np = 0; np < no; ++np) { - if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, state->pre_a_lam + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } + if (i < bits_na_1 && (n = wnaf_na_1[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_na_lam && (n = wnaf_na_lam[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); } if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); @@ -466,11 +372,9 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); } #else - for (np = 0; np < no; ++np) { - if (i < state->ps[np].bits_na && (n = state->ps[np].wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } + if (i < bits_na && (n = wnaf_na[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); } if (i < bits_ng && (n = wnaf_ng[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); @@ -484,528 +388,4 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c } } -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - struct secp256k1_strauss_point_state ps[1]; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; -#endif - struct secp256k1_strauss_state state; - - state.prej = prej; - state.zr = zr; - state.pre_a = pre_a; -#ifdef USE_ENDOMORPHISM - state.pre_a_lam = pre_a_lam; -#endif - state.ps = ps; - secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng); -} - -static size_t secp256k1_strauss_scratch_size(size_t n_points) { -#ifdef USE_ENDOMORPHISM - static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); -#else - static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); -#endif - return n_points*point_size; -} - -static int secp256k1_ecmult_strauss_batch(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { - secp256k1_gej* points; - secp256k1_scalar* scalars; - struct secp256k1_strauss_state state; - size_t i; - - secp256k1_gej_set_infinity(r); - if (inp_g_sc == NULL && n_points == 0) { - return 1; - } - - if (!secp256k1_scratch_resize(scratch, secp256k1_strauss_scratch_size(n_points), STRAUSS_SCRATCH_OBJECTS)) { - return 0; - } - secp256k1_scratch_reset(scratch); - points = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_gej)); - scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_scalar)); - state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej)); - state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe)); -#ifdef USE_ENDOMORPHISM - state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); - state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A); -#else - state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); -#endif - state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(scratch, n_points * sizeof(struct secp256k1_strauss_point_state)); - - for (i = 0; i < n_points; i++) { - secp256k1_ge point; - if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) return 0; - secp256k1_gej_set_ge(&points[i], &point); - } - secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); - return 1; -} - -/* Wrapper for secp256k1_ecmult_multi_func interface */ -static int secp256k1_ecmult_strauss_batch_single(const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { - return secp256k1_ecmult_strauss_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); -} - -static size_t secp256k1_strauss_max_points(secp256k1_scratch *scratch) { - return secp256k1_scratch_max_allocation(scratch, STRAUSS_SCRATCH_OBJECTS) / secp256k1_strauss_scratch_size(1); -} - -/** Convert a number to WNAF notation. - * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. - * It has the following guarantees: - * - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w) - * - the number of words set is always WNAF_SIZE(w) - * - the returned skew is 0 without endomorphism, or 0 or 1 with endomorphism - */ -static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) { - int sign = 0; - int skew = 0; - int pos = 1; -#ifndef USE_ENDOMORPHISM - secp256k1_scalar neg_s; #endif - const secp256k1_scalar *work = s; - - if (secp256k1_scalar_is_zero(s)) { - while (pos * w < WNAF_BITS) { - wnaf[pos] = 0; - ++pos; - } - return 0; - } - - if (secp256k1_scalar_is_even(s)) { -#ifdef USE_ENDOMORPHISM - skew = 1; -#else - secp256k1_scalar_negate(&neg_s, s); - work = &neg_s; - sign = -1; -#endif - } - - wnaf[0] = (secp256k1_scalar_get_bits_var(work, 0, w) + skew + sign) ^ sign; - - while (pos * w < WNAF_BITS) { - int now = w; - int val; - if (now + pos * w > WNAF_BITS) { - now = WNAF_BITS - pos * w; - } - val = secp256k1_scalar_get_bits_var(work, pos * w, now); - if ((val & 1) == 0) { - wnaf[pos - 1] -= ((1 << w) + sign) ^ sign; - wnaf[pos] = (val + 1 + sign) ^ sign; - } else { - wnaf[pos] = (val + sign) ^ sign; - } - ++pos; - } - VERIFY_CHECK(pos == WNAF_SIZE(w)); - - return skew; -} - -struct secp256k1_pippenger_point_state { - int skew_na; - size_t input_pos; -}; - -struct secp256k1_pippenger_state { - int *wnaf_na; - struct secp256k1_pippenger_point_state* ps; -}; - -/* - * pippenger_wnaf computes the result of a multi-point multiplication as - * follows: The scalars are brought into wnaf with n_wnaf elements each. Then - * for every i < n_wnaf, first each point is added to a "bucket" corresponding - * to the point's wnaf[i]. Second, the buckets are added together such that - * r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ... - */ -static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, secp256k1_scalar *sc, secp256k1_ge *pt, size_t num) { - size_t n_wnaf = WNAF_SIZE(bucket_window+1); - size_t np; - size_t no = 0; - int i; - int j; - - for (np = 0; np < num; ++np) { - if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { - continue; - } - state->ps[no].input_pos = np; - state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); - no++; - } - secp256k1_gej_set_infinity(r); - - if (no == 0) { - return 1; - } - - for (i = n_wnaf - 1; i >= 0; i--) { - secp256k1_gej running_sum; - - for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { - secp256k1_gej_set_infinity(&buckets[j]); - } - - for (np = 0; np < no; ++np) { - int n = state->wnaf_na[np*n_wnaf + i]; - struct secp256k1_pippenger_point_state point_state = state->ps[np]; - secp256k1_ge tmp; - int idx; - -#ifdef USE_ENDOMORPHISM - if (i == 0) { - /* correct for wnaf skew */ - int skew = point_state.skew_na; - if (skew) { - secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); - } - } -#endif - if (n > 0) { - idx = (n - 1)/2; - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); - } else if (n < 0) { - idx = -(n + 1)/2; - secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); - } - } - - for(j = 0; j < bucket_window; j++) { - secp256k1_gej_double_var(r, r, NULL); - } - - secp256k1_gej_set_infinity(&running_sum); - /* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ... - * = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ... - * + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...) - * using an intermediate running sum: - * running_sum = bucket[0] + bucket[1] + bucket[2] + ... - * - * The doubling is done implicitly by deferring the final window doubling (of 'r'). - */ - for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); - secp256k1_gej_add_var(r, r, &running_sum, NULL); - } - - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); - secp256k1_gej_double_var(r, r, NULL); - secp256k1_gej_add_var(r, r, &running_sum, NULL); - } - return 1; -} - -/** - * Returns optimal bucket_window (number of bits of a scalar represented by a - * set of buckets) for a given number of points. - */ -static int secp256k1_pippenger_bucket_window(size_t n) { -#ifdef USE_ENDOMORPHISM - if (n <= 1) { - return 1; - } else if (n <= 4) { - return 2; - } else if (n <= 20) { - return 3; - } else if (n <= 57) { - return 4; - } else if (n <= 136) { - return 5; - } else if (n <= 235) { - return 6; - } else if (n <= 1260) { - return 7; - } else if (n <= 4420) { - return 9; - } else if (n <= 7880) { - return 10; - } else if (n <= 16050) { - return 11; - } else { - return PIPPENGER_MAX_BUCKET_WINDOW; - } -#else - if (n <= 1) { - return 1; - } else if (n <= 11) { - return 2; - } else if (n <= 45) { - return 3; - } else if (n <= 100) { - return 4; - } else if (n <= 275) { - return 5; - } else if (n <= 625) { - return 6; - } else if (n <= 1850) { - return 7; - } else if (n <= 3400) { - return 8; - } else if (n <= 9630) { - return 9; - } else if (n <= 17900) { - return 10; - } else if (n <= 32800) { - return 11; - } else { - return PIPPENGER_MAX_BUCKET_WINDOW; - } -#endif -} - -/** - * Returns the maximum optimal number of points for a bucket_window. - */ -static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) { - switch(bucket_window) { -#ifdef USE_ENDOMORPHISM - case 1: return 1; - case 2: return 4; - case 3: return 20; - case 4: return 57; - case 5: return 136; - case 6: return 235; - case 7: return 1260; - case 8: return 1260; - case 9: return 4420; - case 10: return 7880; - case 11: return 16050; - case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; -#else - case 1: return 1; - case 2: return 11; - case 3: return 45; - case 4: return 100; - case 5: return 275; - case 6: return 625; - case 7: return 1850; - case 8: return 3400; - case 9: return 9630; - case 10: return 17900; - case 11: return 32800; - case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; -#endif - } - return 0; -} - - -#ifdef USE_ENDOMORPHISM -SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) { - secp256k1_scalar tmp = *s1; - secp256k1_scalar_split_lambda(s1, s2, &tmp); - secp256k1_ge_mul_lambda(p2, p1); - - if (secp256k1_scalar_is_high(s1)) { - secp256k1_scalar_negate(s1, s1); - secp256k1_ge_neg(p1, p1); - } - if (secp256k1_scalar_is_high(s2)) { - secp256k1_scalar_negate(s2, s2); - secp256k1_ge_neg(p2, p2); - } -} -#endif - -/** - * Returns the scratch size required for a given number of points (excluding - * base point G) without considering alignment. - */ -static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) { -#ifdef USE_ENDOMORPHISM - size_t entries = 2*n_points + 2; -#else - size_t entries = n_points + 1; -#endif - size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); - return ((1<ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(scratch, entries * sizeof(*state_space->ps)); - state_space->wnaf_na = (int *) secp256k1_scratch_alloc(scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); - buckets = (secp256k1_gej *) secp256k1_scratch_alloc(scratch, (1<ps[i].skew_na = 0; - for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) { - state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0; - } - } - for(i = 0; i < 1< max_alloc) { - break; - } - space_for_points = max_alloc - space_overhead; - - n_points = space_for_points/entry_size; - n_points = n_points > max_points ? max_points : n_points; - if (n_points > res) { - res = n_points; - } - if (n_points < max_points) { - /* A larger bucket_window may support even more points. But if we - * would choose that then the caller couldn't safely use any number - * smaller than what this function returns */ - break; - } - } - return res; -} - -typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t); -static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { - size_t i; - - int (*f)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t); - size_t max_points; - size_t n_batches; - size_t n_batch_points; - - secp256k1_gej_set_infinity(r); - if (inp_g_sc == NULL && n == 0) { - return 1; - } else if (n == 0) { - secp256k1_scalar szero; - secp256k1_scalar_set_int(&szero, 0); - secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc); - return 1; - } - - max_points = secp256k1_pippenger_max_points(scratch); - if (max_points == 0) { - return 0; - } else if (max_points > ECMULT_MAX_POINTS_PER_BATCH) { - max_points = ECMULT_MAX_POINTS_PER_BATCH; - } - n_batches = (n+max_points-1)/max_points; - n_batch_points = (n+n_batches-1)/n_batches; - - if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { - f = secp256k1_ecmult_pippenger_batch; - } else { - max_points = secp256k1_strauss_max_points(scratch); - if (max_points == 0) { - return 0; - } - n_batches = (n+max_points-1)/max_points; - n_batch_points = (n+n_batches-1)/n_batches; - f = secp256k1_ecmult_strauss_batch; - } - for(i = 0; i < n_batches; i++) { - size_t nbp = n < n_batch_points ? n : n_batch_points; - size_t offset = n_batch_points*i; - secp256k1_gej tmp; - if (!f(ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { - return 0; - } - secp256k1_gej_add_var(r, r, &tmp, NULL); - n -= nbp; - } - return 1; -} - -#endif /* SECP256K1_ECMULT_IMPL_H */ diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h index bb6692ad..4daefc43 100644 --- a/src/secp256k1/src/field.h +++ b/src/secp256k1/src/field.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_H -#define SECP256K1_FIELD_H +#ifndef _SECP256K1_FIELD_ +#define _SECP256K1_FIELD_ /** Field element module. * @@ -30,8 +30,6 @@ #error "Please select field implementation" #endif -#include "util.h" - /** Normalize a field element. */ static void secp256k1_fe_normalize(secp256k1_fe *r); @@ -52,9 +50,6 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); /** Set a field element equal to a small integer. Resulting field element is normalized. */ static void secp256k1_fe_set_int(secp256k1_fe *r, int a); -/** Sets a field element equal to zero, initializing all fields. */ -static void secp256k1_fe_clear(secp256k1_fe *a); - /** Verify whether a field element is zero. Requires the input to be normalized. */ static int secp256k1_fe_is_zero(const secp256k1_fe *a); @@ -129,4 +124,4 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); -#endif /* SECP256K1_FIELD_H */ +#endif diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h index 727c5267..61ee1e09 100644 --- a/src/secp256k1/src/field_10x26.h +++ b/src/secp256k1/src/field_10x26.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_REPR_H -#define SECP256K1_FIELD_REPR_H +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ #include @@ -44,5 +44,4 @@ typedef struct { #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] - -#endif /* SECP256K1_FIELD_REPR_H */ +#endif diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h index 94f8132f..7b8c0796 100644 --- a/src/secp256k1/src/field_10x26_impl.h +++ b/src/secp256k1/src/field_10x26_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_REPR_IMPL_H -#define SECP256K1_FIELD_REPR_IMPL_H +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ #include "util.h" #include "num.h" @@ -38,6 +38,10 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } +#else +static void secp256k1_fe_verify(const secp256k1_fe *a) { + (void)a; +} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -321,17 +325,17 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); - r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); - r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); - r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18); - r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24); - r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22); - r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20); - r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18); - r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); - r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); - + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; + } + } if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { return 0; } @@ -345,42 +349,21 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - r[0] = (a->n[9] >> 14) & 0xff; - r[1] = (a->n[9] >> 6) & 0xff; - r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); - r[3] = (a->n[8] >> 16) & 0xff; - r[4] = (a->n[8] >> 8) & 0xff; - r[5] = a->n[8] & 0xff; - r[6] = (a->n[7] >> 18) & 0xff; - r[7] = (a->n[7] >> 10) & 0xff; - r[8] = (a->n[7] >> 2) & 0xff; - r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f); - r[10] = (a->n[6] >> 12) & 0xff; - r[11] = (a->n[6] >> 4) & 0xff; - r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf); - r[13] = (a->n[5] >> 14) & 0xff; - r[14] = (a->n[5] >> 6) & 0xff; - r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3); - r[16] = (a->n[4] >> 16) & 0xff; - r[17] = (a->n[4] >> 8) & 0xff; - r[18] = a->n[4] & 0xff; - r[19] = (a->n[3] >> 18) & 0xff; - r[20] = (a->n[3] >> 10) & 0xff; - r[21] = (a->n[3] >> 2) & 0xff; - r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f); - r[23] = (a->n[2] >> 12) & 0xff; - r[24] = (a->n[2] >> 4) & 0xff; - r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf); - r[26] = (a->n[1] >> 14) & 0xff; - r[27] = (a->n[1] >> 6) & 0xff; - r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3); - r[29] = (a->n[0] >> 16) & 0xff; - r[30] = (a->n[0] >> 8) & 0xff; - r[31] = a->n[0] & 0xff; + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); + } + r[31-i] = c; + } } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { @@ -1158,4 +1141,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif /* SECP256K1_FIELD_REPR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h index bccd8feb..8e69a560 100644 --- a/src/secp256k1/src/field_5x52.h +++ b/src/secp256k1/src/field_5x52.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_REPR_H -#define SECP256K1_FIELD_REPR_H +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ #include @@ -44,4 +44,4 @@ typedef struct { (d6) | (((uint64_t)(d7)) << 32) \ }} -#endif /* SECP256K1_FIELD_REPR_H */ +#endif diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h index 1fc3171f..98cc004b 100644 --- a/src/secp256k1/src/field_5x52_asm_impl.h +++ b/src/secp256k1/src/field_5x52_asm_impl.h @@ -11,8 +11,8 @@ * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly */ -#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H -#define SECP256K1_FIELD_INNER5X52_IMPL_H +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { /** @@ -499,4 +499,4 @@ __asm__ __volatile__( ); } -#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ +#endif diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h index 957c61b0..7a99eb21 100644 --- a/src/secp256k1/src/field_5x52_impl.h +++ b/src/secp256k1/src/field_5x52_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_REPR_IMPL_H -#define SECP256K1_FIELD_REPR_IMPL_H +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -49,6 +49,10 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } +#else +static void secp256k1_fe_verify(const secp256k1_fe *a) { + (void)a; +} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -284,40 +288,16 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - r->n[0] = (uint64_t)a[31] - | ((uint64_t)a[30] << 8) - | ((uint64_t)a[29] << 16) - | ((uint64_t)a[28] << 24) - | ((uint64_t)a[27] << 32) - | ((uint64_t)a[26] << 40) - | ((uint64_t)(a[25] & 0xF) << 48); - r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) - | ((uint64_t)a[24] << 4) - | ((uint64_t)a[23] << 12) - | ((uint64_t)a[22] << 20) - | ((uint64_t)a[21] << 28) - | ((uint64_t)a[20] << 36) - | ((uint64_t)a[19] << 44); - r->n[2] = (uint64_t)a[18] - | ((uint64_t)a[17] << 8) - | ((uint64_t)a[16] << 16) - | ((uint64_t)a[15] << 24) - | ((uint64_t)a[14] << 32) - | ((uint64_t)a[13] << 40) - | ((uint64_t)(a[12] & 0xF) << 48); - r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) - | ((uint64_t)a[11] << 4) - | ((uint64_t)a[10] << 12) - | ((uint64_t)a[9] << 20) - | ((uint64_t)a[8] << 28) - | ((uint64_t)a[7] << 36) - | ((uint64_t)a[6] << 44); - r->n[4] = (uint64_t)a[5] - | ((uint64_t)a[4] << 8) - | ((uint64_t)a[3] << 16) - | ((uint64_t)a[2] << 24) - | ((uint64_t)a[1] << 32) - | ((uint64_t)a[0] << 40); + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; + } + } if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { return 0; } @@ -331,42 +311,21 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - r[0] = (a->n[4] >> 40) & 0xFF; - r[1] = (a->n[4] >> 32) & 0xFF; - r[2] = (a->n[4] >> 24) & 0xFF; - r[3] = (a->n[4] >> 16) & 0xFF; - r[4] = (a->n[4] >> 8) & 0xFF; - r[5] = a->n[4] & 0xFF; - r[6] = (a->n[3] >> 44) & 0xFF; - r[7] = (a->n[3] >> 36) & 0xFF; - r[8] = (a->n[3] >> 28) & 0xFF; - r[9] = (a->n[3] >> 20) & 0xFF; - r[10] = (a->n[3] >> 12) & 0xFF; - r[11] = (a->n[3] >> 4) & 0xFF; - r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); - r[13] = (a->n[2] >> 40) & 0xFF; - r[14] = (a->n[2] >> 32) & 0xFF; - r[15] = (a->n[2] >> 24) & 0xFF; - r[16] = (a->n[2] >> 16) & 0xFF; - r[17] = (a->n[2] >> 8) & 0xFF; - r[18] = a->n[2] & 0xFF; - r[19] = (a->n[1] >> 44) & 0xFF; - r[20] = (a->n[1] >> 36) & 0xFF; - r[21] = (a->n[1] >> 28) & 0xFF; - r[22] = (a->n[1] >> 20) & 0xFF; - r[23] = (a->n[1] >> 12) & 0xFF; - r[24] = (a->n[1] >> 4) & 0xFF; - r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); - r[26] = (a->n[0] >> 40) & 0xFF; - r[27] = (a->n[0] >> 32) & 0xFF; - r[28] = (a->n[0] >> 24) & 0xFF; - r[29] = (a->n[0] >> 16) & 0xFF; - r[30] = (a->n[0] >> 8) & 0xFF; - r[31] = a->n[0] & 0xFF; + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); + } + r[31-i] = c; + } } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { @@ -493,4 +452,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif /* SECP256K1_FIELD_REPR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h index 95a0d179..0bf22bdd 100644 --- a/src/secp256k1/src/field_5x52_int128_impl.h +++ b/src/secp256k1/src/field_5x52_int128_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H -#define SECP256K1_FIELD_INNER5X52_IMPL_H +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ #include @@ -274,4 +274,4 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ +#endif diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h index 20428648..5127b279 100644 --- a/src/secp256k1/src/field_impl.h +++ b/src/secp256k1/src/field_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_FIELD_IMPL_H -#define SECP256K1_FIELD_IMPL_H +#ifndef _SECP256K1_FIELD_IMPL_H_ +#define _SECP256K1_FIELD_IMPL_H_ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -312,4 +312,4 @@ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { #endif } -#endif /* SECP256K1_FIELD_IMPL_H */ +#endif diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c index 87d296eb..1835fd49 100644 --- a/src/secp256k1/src/gen_context.c +++ b/src/secp256k1/src/gen_context.c @@ -41,7 +41,7 @@ int main(int argc, char **argv) { fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#include \"src/group.h\"\n"); + fprintf(fp, "#include \"group.h\"\n"); fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index 3947ea2d..4957b248 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_GROUP_H -#define SECP256K1_GROUP_H +#ifndef _SECP256K1_GROUP_ +#define _SECP256K1_GROUP_ #include "num.h" #include "field.h" @@ -79,9 +79,6 @@ static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej * stored in globalz. */ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); -/** Set a group element (affine) equal to the point at infinity. */ -static void secp256k1_ge_set_infinity(secp256k1_ge *r); - /** Set a group element (jacobian) equal to the point at infinity. */ static void secp256k1_gej_set_infinity(secp256k1_gej *r); @@ -144,4 +141,4 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); -#endif /* SECP256K1_GROUP_H */ +#endif diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index b1ace87b..18f2b373 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -4,60 +4,13 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_GROUP_IMPL_H -#define SECP256K1_GROUP_IMPL_H +#ifndef _SECP256K1_GROUP_IMPL_H_ +#define _SECP256K1_GROUP_IMPL_H_ #include "num.h" #include "field.h" #include "group.h" -/* These points can be generated in sage as follows: - * - * 0. Setup a worksheet with the following parameters. - * b = 4 # whatever CURVE_B will be set to - * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) - * C = EllipticCurve ([F (0), F (b)]) - * - * 1. Determine all the small orders available to you. (If there are - * no satisfactory ones, go back and change b.) - * print C.order().factor(limit=1000) - * - * 2. Choose an order as one of the prime factors listed in the above step. - * (You can also multiply some to get a composite order, though the - * tests will crash trying to invert scalars during signing.) We take a - * random point and scale it to drop its order to the desired value. - * There is some probability this won't work; just try again. - * order = 199 - * P = C.random_point() - * P = (int(P.order()) / int(order)) * P - * assert(P.order() == order) - * - * 3. Print the values. You'll need to use a vim macro or something to - * split the hex output into 4-byte chunks. - * print "%x %x" % P.xy() - */ -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 199 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, - 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, - 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, - 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED -); - -const int CURVE_B = 4; -# elif EXHAUSTIVE_TEST_ORDER == 13 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, - 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, - 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, - 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac -); -const int CURVE_B = 2; -# else -# error No known generator for the specified exhaustive test group order. -# endif -#else /** Generator for secp256k1, value 'g' defined in * "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ @@ -68,9 +21,6 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL ); -const int CURVE_B = 7; -#endif - static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; @@ -195,15 +145,9 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp static void secp256k1_gej_set_infinity(secp256k1_gej *r) { r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); -} - -static void secp256k1_ge_set_infinity(secp256k1_ge *r) { - r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); + secp256k1_fe_set_int(&r->x, 0); + secp256k1_fe_set_int(&r->y, 0); + secp256k1_fe_set_int(&r->z, 0); } static void secp256k1_gej_clear(secp256k1_gej *r) { @@ -225,7 +169,7 @@ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; - secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_set_int(&c, 7); secp256k1_fe_add(&c, &x3); return secp256k1_fe_sqrt(&r->y, &c); } @@ -284,7 +228,7 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); - secp256k1_fe_mul_int(&z6, CURVE_B); + secp256k1_fe_mul_int(&z6, 7); secp256k1_fe_add(&x3, &z6); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); @@ -298,7 +242,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { /* y^2 = x^3 + 7 */ secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_set_int(&c, 7); secp256k1_fe_add(&x3, &c); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); @@ -703,4 +647,4 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { return secp256k1_fe_is_quad_var(&yz); } -#endif /* SECP256K1_GROUP_IMPL_H */ +#endif diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h index de26e4b8..fca98cab 100644 --- a/src/secp256k1/src/hash.h +++ b/src/secp256k1/src/hash.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_HASH_H -#define SECP256K1_HASH_H +#ifndef _SECP256K1_HASH_ +#define _SECP256K1_HASH_ #include #include @@ -14,28 +14,28 @@ typedef struct { uint32_t s[8]; uint32_t buf[16]; /* In big endian */ size_t bytes; -} secp256k1_sha256; +} secp256k1_sha256_t; -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); typedef struct { - secp256k1_sha256 inner, outer; -} secp256k1_hmac_sha256; + secp256k1_sha256_t inner, outer; +} secp256k1_hmac_sha256_t; -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); typedef struct { unsigned char v[32]; unsigned char k[32]; int retry; -} secp256k1_rfc6979_hmac_sha256; +} secp256k1_rfc6979_hmac_sha256_t; -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); -#endif /* SECP256K1_HASH_H */ +#endif diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h index 009f26be..b47e65f8 100644 --- a/src/secp256k1/src/hash_impl.h +++ b/src/secp256k1/src/hash_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_HASH_IMPL_H -#define SECP256K1_HASH_IMPL_H +#ifndef _SECP256K1_HASH_IMPL_H_ +#define _SECP256K1_HASH_IMPL_H_ #include "hash.h" @@ -33,7 +33,7 @@ #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #endif -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; @@ -128,15 +128,14 @@ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { s[7] += h; } -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; while (bufsize + len >= 64) { /* Fill the buffer, and process it. */ - size_t chunk_len = 64 - bufsize; - memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); - data += chunk_len; - len -= chunk_len; + memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); + data += 64 - bufsize; + len -= 64 - bufsize; secp256k1_sha256_transform(hash->s, hash->buf); bufsize = 0; } @@ -146,7 +145,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char * } } -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t sizedesc[2]; uint32_t out[8]; @@ -162,14 +161,14 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out memcpy(out32, (const unsigned char*)out, 32); } -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { - size_t n; +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { + int n; unsigned char rkey[64]; - if (keylen <= sizeof(rkey)) { + if (keylen <= 64) { memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, sizeof(rkey) - keylen); + memset(rkey + keylen, 0, 64 - keylen); } else { - secp256k1_sha256 sha256; + secp256k1_sha256_t sha256; secp256k1_sha256_initialize(&sha256); secp256k1_sha256_write(&sha256, key, keylen); secp256k1_sha256_finalize(&sha256, rkey); @@ -177,24 +176,24 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const } secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < sizeof(rkey); n++) { + for (n = 0; n < 64; n++) { rkey[n] ^= 0x5c; } - secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); + secp256k1_sha256_write(&hash->outer, rkey, 64); secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < sizeof(rkey); n++) { + for (n = 0; n < 64; n++) { rkey[n] ^= 0x5c ^ 0x36; } - secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); - memset(rkey, 0, sizeof(rkey)); + secp256k1_sha256_write(&hash->inner, rkey, 64); + memset(rkey, 0, 64); } -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { secp256k1_sha256_write(&hash->inner, data, size); } -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { unsigned char temp[32]; secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_write(&hash->outer, temp, 32); @@ -203,8 +202,8 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256 hmac; +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { + secp256k1_hmac_sha256_t hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -233,11 +232,11 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 rng->retry = 0; } -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { - secp256k1_hmac_sha256 hmac; + secp256k1_hmac_sha256_t hmac; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); @@ -248,7 +247,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 } while (outlen > 0) { - secp256k1_hmac_sha256 hmac; + secp256k1_hmac_sha256_t hmac; int now = outlen; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); @@ -264,7 +263,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 rng->retry = 1; } -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { memset(rng->k, 0, 32); memset(rng->v, 0, 32); rng->retry = 0; @@ -279,4 +278,4 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 #undef Maj #undef Ch -#endif /* SECP256K1_HASH_IMPL_H */ +#endif diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java index 1c67802f..be67048f 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -32,7 +32,7 @@ *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

* *

To build secp256k1 for use with bitcoinj, run - * `./configure --enable-jni --enable-experimental --enable-module-ecdh` + * `./configure --enable-jni --enable-experimental --enable-module-schnorr --enable-module-ecdh` * and `make` then copy `.libs/libsecp256k1.so` to your system library path * or point the JVM to the folder containing it with -Djava.library.path *

@@ -417,6 +417,36 @@ public static synchronized boolean randomize(byte[] seed) throws AssertFailExcep } } + public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException { + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] sigArr = retByteArray[0]; + int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + + assertEquals(sigArr.length, 64, "Got bad signature length."); + + return retVal == 0 ? new byte[0] : sigArr; + } + private static native long secp256k1_ctx_clone(long context); private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); @@ -441,6 +471,8 @@ public static synchronized boolean randomize(byte[] seed) throws AssertFailExcep private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); + private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); + private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); } diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java index c00d0889..f18ce958 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -167,6 +167,22 @@ public static void testRandomize() throws AssertFailException { assertEquals( result, true, "testRandomize"); } + /** + * This tests signSchnorr() for a valid secretkey + */ + public static void testSchnorrSign() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "C5E929AA058B982048760422D3B563749B7D0E50C5EBD8CD2FFC23214BD6A2F1B072C13880997EBA847CF20F2F90FCE07C1CA33A890A4127095A351127F8D95F" , "testSchnorrSign"); + } + + /** + * This tests signSchnorr() for a valid secretkey + */ public static void testCreateECDHSecret() throws AssertFailException{ byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); @@ -200,6 +216,11 @@ public static void main(String[] args) throws AssertFailException{ testSignPos(); testSignNeg(); + //Test Schnorr (partial support) //TODO + testSchnorrSign(); + //testSchnorrVerify + //testSchnorrRecovery + //Test privKeyTweakAdd() 1 testPrivKeyTweakAdd_1(); diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c index bcef7b32..dba9524d 100644 --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -5,6 +5,7 @@ #include "include/secp256k1.h" #include "include/secp256k1_ecdh.h" #include "include/secp256k1_recovery.h" +#include "include/secp256k1_schnorr.h" SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone @@ -332,6 +333,39 @@ SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1p return 0; } +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[1]; + unsigned char sig[64]; + + int ret = secp256k1_schnorr_sign(ctx, sig, data, secKey, NULL, NULL); + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, 64); + (*env)->SetByteArrayRegion(env, sigArray, 0, 64, (jbyte*)sig); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) { diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h index fe613c9e..4125a1f5 100644 --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -104,6 +104,14 @@ SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1e SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse (JNIEnv *, jclass, jobject, jlong, jint); +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_schnorr_sign + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l); + /* * Class: org_bitcoin_NativeSecp256k1 * Method: secp256k1_ecdh diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h index bd8739ee..c23e4f82 100644 --- a/src/secp256k1/src/modules/ecdh/main_impl.h +++ b/src/secp256k1/src/modules/ecdh/main_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_MODULE_ECDH_MAIN_H -#define SECP256K1_MODULE_ECDH_MAIN_H +#ifndef _SECP256K1_MODULE_ECDH_MAIN_ +#define _SECP256K1_MODULE_ECDH_MAIN_ #include "include/secp256k1_ecdh.h" #include "ecmult_const_impl.h" @@ -16,10 +16,10 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se secp256k1_gej res; secp256k1_ge pt; secp256k1_scalar s; - VERIFY_CHECK(ctx != NULL); ARG_CHECK(result != NULL); ARG_CHECK(point != NULL); ARG_CHECK(scalar != NULL); + (void)ctx; secp256k1_pubkey_load(ctx, &pt, point); secp256k1_scalar_set_b32(&s, scalar, &overflow); @@ -28,7 +28,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se } else { unsigned char x[32]; unsigned char y[1]; - secp256k1_sha256 sha; + secp256k1_sha256_t sha; secp256k1_ecmult_const(&res, &pt, &s); secp256k1_ge_set_gej(&pt, &res); @@ -51,4 +51,4 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se return ret; } -#endif /* SECP256K1_MODULE_ECDH_MAIN_H */ +#endif diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h index 0c53f8ee..7badc903 100644 --- a/src/secp256k1/src/modules/ecdh/tests_impl.h +++ b/src/secp256k1/src/modules/ecdh/tests_impl.h @@ -4,37 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_MODULE_ECDH_TESTS_H -#define SECP256K1_MODULE_ECDH_TESTS_H - -void test_ecdh_api(void) { - /* Setup context that just counts errors */ - secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_pubkey point; - unsigned char res[32]; - unsigned char s_one[32] = { 0 }; - int32_t ecount = 0; - s_one[31] = 1; - - secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); - CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); - - /* Check all NULLs are detected */ - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 3); - - /* Cleanup */ - secp256k1_context_destroy(tctx); -} +#ifndef _SECP256K1_MODULE_ECDH_TESTS_ +#define _SECP256K1_MODULE_ECDH_TESTS_ void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; @@ -44,7 +15,7 @@ void test_ecdh_generator_basepoint(void) { s_one[31] = 1; /* Check against pubkey creation when the basepoint is the generator */ for (i = 0; i < 100; ++i) { - secp256k1_sha256 sha; + secp256k1_sha256_t sha; unsigned char s_b32[32]; unsigned char output_ecdh[32]; unsigned char output_ser[32]; @@ -97,9 +68,8 @@ void test_bad_scalar(void) { } void run_ecdh_tests(void) { - test_ecdh_api(); test_ecdh_generator_basepoint(); test_bad_scalar(); } -#endif /* SECP256K1_MODULE_ECDH_TESTS_H */ +#endif diff --git a/src/secp256k1/src/modules/recovery/main_impl.h b/src/secp256k1/src/modules/recovery/main_impl.h index 2f6691c5..86f2f0cb 100644 --- a/src/secp256k1/src/modules/recovery/main_impl.h +++ b/src/secp256k1/src/modules/recovery/main_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H -#define SECP256K1_MODULE_RECOVERY_MAIN_H +#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ +#define _SECP256K1_MODULE_RECOVERY_MAIN_ #include "include/secp256k1_recovery.h" @@ -179,7 +179,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk ARG_CHECK(pubkey != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ + ARG_CHECK(recid >= 0 && recid < 4); secp256k1_scalar_set_b32(&m, msg32, NULL); if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { secp256k1_pubkey_save(pubkey, &q); @@ -190,4 +190,4 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk } } -#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */ +#endif diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h index 5c9bbe86..8932d5f0 100644 --- a/src/secp256k1/src/modules/recovery/tests_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_impl.h @@ -4,148 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_MODULE_RECOVERY_TESTS_H -#define SECP256K1_MODULE_RECOVERY_TESTS_H - -static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void) msg32; - (void) key32; - (void) algo16; - (void) data; - - /* On the first run, return 0 to force a second run */ - if (counter == 0) { - memset(nonce32, 0, 32); - return 1; - } - /* On the second run, return an overflow to force a third run */ - if (counter == 1) { - memset(nonce32, 0xff, 32); - return 1; - } - /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ - memset(nonce32, 1, 32); - return secp256k1_rand_bits(1); -} - -void test_ecdsa_recovery_api(void) { - /* Setup contexts that just count errors */ - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - secp256k1_ecdsa_signature normal_sig; - secp256k1_ecdsa_recoverable_signature recsig; - unsigned char privkey[32] = { 1 }; - unsigned char message[32] = { 2 }; - int32_t ecount = 0; - int recid = 0; - unsigned char sig[74]; - unsigned char zero_privkey[32] = { 0 }; - unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Check bad contexts and NULLs for signing */ - ecount = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); - CHECK(ecount == 5); - /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ - secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); - CHECK(ecount == 5); - /* These will all fail, but not in ARG_CHECK way */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); - /* This one will succeed. */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 5); - - /* Check signing with a goofy nonce function */ - - /* Check bad contexts and NULLs for recovery */ - ecount = 0; - CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); - CHECK(ecount == 5); - - /* Check NULLs for conversion */ - CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); - - /* Check NULLs for de/serialization */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); - CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); - CHECK(ecount == 7); - /* overflow in signature will fail but not affect ecount */ - memcpy(sig, over_privkey, 32); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); - CHECK(ecount == 7); - - /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); -} +#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ +#define _SECP256K1_MODULE_RECOVERY_TESTS_ void test_ecdsa_recovery_end_to_end(void) { unsigned char extra[32] = {0x00}; @@ -381,13 +241,10 @@ void test_ecdsa_recovery_edge_cases(void) { void run_recovery_tests(void) { int i; - for (i = 0; i < count; i++) { - test_ecdsa_recovery_api(); - } for (i = 0; i < 64*count; i++) { test_ecdsa_recovery_end_to_end(); } test_ecdsa_recovery_edge_cases(); } -#endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */ +#endif diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h index 49f2dd79..7bb9c5be 100644 --- a/src/secp256k1/src/num.h +++ b/src/secp256k1/src/num.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_NUM_H -#define SECP256K1_NUM_H +#ifndef _SECP256K1_NUM_ +#define _SECP256K1_NUM_ #ifndef USE_NUM_NONE @@ -71,4 +71,4 @@ static void secp256k1_num_negate(secp256k1_num *r); #endif -#endif /* SECP256K1_NUM_H */ +#endif diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h index 3619844b..7dd81308 100644 --- a/src/secp256k1/src/num_gmp.h +++ b/src/secp256k1/src/num_gmp.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_NUM_REPR_H -#define SECP256K1_NUM_REPR_H +#ifndef _SECP256K1_NUM_REPR_ +#define _SECP256K1_NUM_REPR_ #include @@ -17,4 +17,4 @@ typedef struct { int limbs; } secp256k1_num; -#endif /* SECP256K1_NUM_REPR_H */ +#endif diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h index 0ae2a8ba..3a46495e 100644 --- a/src/secp256k1/src/num_gmp_impl.h +++ b/src/secp256k1/src/num_gmp_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_NUM_REPR_IMPL_H -#define SECP256K1_NUM_REPR_IMPL_H +#ifndef _SECP256K1_NUM_REPR_IMPL_H_ +#define _SECP256K1_NUM_REPR_IMPL_H_ #include #include @@ -285,4 +285,4 @@ static void secp256k1_num_negate(secp256k1_num *r) { r->neg ^= 1; } -#endif /* SECP256K1_NUM_REPR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h index c45193b0..0b0e3a07 100644 --- a/src/secp256k1/src/num_impl.h +++ b/src/secp256k1/src/num_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_NUM_IMPL_H -#define SECP256K1_NUM_IMPL_H +#ifndef _SECP256K1_NUM_IMPL_H_ +#define _SECP256K1_NUM_IMPL_H_ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -21,4 +21,4 @@ #error "Please select num implementation" #endif -#endif /* SECP256K1_NUM_IMPL_H */ +#endif diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h index 59304cb6..b590ccd6 100644 --- a/src/secp256k1/src/scalar.h +++ b/src/secp256k1/src/scalar.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_H -#define SECP256K1_SCALAR_H +#ifndef _SECP256K1_SCALAR_ +#define _SECP256K1_SCALAR_ #include "num.h" @@ -13,9 +13,7 @@ #include "libsecp256k1-config.h" #endif -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low.h" -#elif defined(USE_SCALAR_4X64) +#if defined(USE_SCALAR_4X64) #include "scalar_4x64.h" #elif defined(USE_SCALAR_8X32) #include "scalar_8x32.h" @@ -103,4 +101,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); -#endif /* SECP256K1_SCALAR_H */ +#endif diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h index 19c7495d..cff40603 100644 --- a/src/secp256k1/src/scalar_4x64.h +++ b/src/secp256k1/src/scalar_4x64.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ #include @@ -16,4 +16,4 @@ typedef struct { #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} -#endif /* SECP256K1_SCALAR_REPR_H */ +#endif diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h index db1ebf94..56e7bd82 100644 --- a/src/secp256k1/src/scalar_4x64_impl.h +++ b/src/secp256k1/src/scalar_4x64_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) @@ -946,4 +946,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); } -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h index 2c9a348e..1319664f 100644 --- a/src/secp256k1/src/scalar_8x32.h +++ b/src/secp256k1/src/scalar_8x32.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ #include @@ -16,4 +16,4 @@ typedef struct { #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} -#endif /* SECP256K1_SCALAR_REPR_H */ +#endif diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h index 4f9ed61f..aae4f35c 100644 --- a/src/secp256k1/src/scalar_8x32_impl.h +++ b/src/secp256k1/src/scalar_8x32_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint32_t)0xD0364141UL) @@ -718,4 +718,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); } -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index fa790570..c5baf4df 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_SCALAR_IMPL_H -#define SECP256K1_SCALAR_IMPL_H +#ifndef _SECP256K1_SCALAR_IMPL_H_ +#define _SECP256K1_SCALAR_IMPL_H_ #include "group.h" #include "scalar.h" @@ -14,9 +14,7 @@ #include "libsecp256k1-config.h" #endif -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low_impl.h" -#elif defined(USE_SCALAR_4X64) +#if defined(USE_SCALAR_4X64) #include "scalar_4x64_impl.h" #elif defined(USE_SCALAR_8X32) #include "scalar_8x32_impl.h" @@ -33,112 +31,101 @@ static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a /** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ static void secp256k1_scalar_order_get_num(secp256k1_num *r) { -#if defined(EXHAUSTIVE_TEST_ORDER) - static const unsigned char order[32] = { - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER - }; -#else static const unsigned char order[32] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 }; -#endif secp256k1_num_set_bin(r, order, 32); } #endif static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { -#if defined(EXHAUSTIVE_TEST_ORDER) - int i; - *r = 0; - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) - if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) - *r = i; - /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus - * have a composite group order; fix it in exhaustive_tests.c). */ - VERIFY_CHECK(*r != 0); -} -#else secp256k1_scalar *t; int i; - /* First compute xN as x ^ (2^N - 1) for some values of N, - * and uM as x ^ M for some values of M. */ - secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126; - secp256k1_scalar u2, u5, u9, u11, u13; + /* First compute x ^ (2^N - 1) for some values of N. */ + secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; + + secp256k1_scalar_sqr(&x2, x); + secp256k1_scalar_mul(&x2, &x2, x); - secp256k1_scalar_sqr(&u2, x); - secp256k1_scalar_mul(&x2, &u2, x); - secp256k1_scalar_mul(&u5, &u2, &x2); - secp256k1_scalar_mul(&x3, &u5, &u2); - secp256k1_scalar_mul(&u9, &x3, &u2); - secp256k1_scalar_mul(&u11, &u9, &u2); - secp256k1_scalar_mul(&u13, &u11, &u2); + secp256k1_scalar_sqr(&x3, &x2); + secp256k1_scalar_mul(&x3, &x3, x); - secp256k1_scalar_sqr(&x6, &u13); + secp256k1_scalar_sqr(&x4, &x3); + secp256k1_scalar_mul(&x4, &x4, x); + + secp256k1_scalar_sqr(&x6, &x4); secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &u11); + secp256k1_scalar_mul(&x6, &x6, &x2); + + secp256k1_scalar_sqr(&x7, &x6); + secp256k1_scalar_mul(&x7, &x7, x); - secp256k1_scalar_sqr(&x8, &x6); - secp256k1_scalar_sqr(&x8, &x8); - secp256k1_scalar_mul(&x8, &x8, &x2); + secp256k1_scalar_sqr(&x8, &x7); + secp256k1_scalar_mul(&x8, &x8, x); - secp256k1_scalar_sqr(&x14, &x8); - for (i = 0; i < 5; i++) { - secp256k1_scalar_sqr(&x14, &x14); + secp256k1_scalar_sqr(&x15, &x8); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x15, &x15); } - secp256k1_scalar_mul(&x14, &x14, &x6); + secp256k1_scalar_mul(&x15, &x15, &x7); - secp256k1_scalar_sqr(&x28, &x14); - for (i = 0; i < 13; i++) { - secp256k1_scalar_sqr(&x28, &x28); + secp256k1_scalar_sqr(&x30, &x15); + for (i = 0; i < 14; i++) { + secp256k1_scalar_sqr(&x30, &x30); } - secp256k1_scalar_mul(&x28, &x28, &x14); + secp256k1_scalar_mul(&x30, &x30, &x15); - secp256k1_scalar_sqr(&x56, &x28); - for (i = 0; i < 27; i++) { - secp256k1_scalar_sqr(&x56, &x56); + secp256k1_scalar_sqr(&x60, &x30); + for (i = 0; i < 29; i++) { + secp256k1_scalar_sqr(&x60, &x60); } - secp256k1_scalar_mul(&x56, &x56, &x28); + secp256k1_scalar_mul(&x60, &x60, &x30); - secp256k1_scalar_sqr(&x112, &x56); - for (i = 0; i < 55; i++) { - secp256k1_scalar_sqr(&x112, &x112); + secp256k1_scalar_sqr(&x120, &x60); + for (i = 0; i < 59; i++) { + secp256k1_scalar_sqr(&x120, &x120); } - secp256k1_scalar_mul(&x112, &x112, &x56); + secp256k1_scalar_mul(&x120, &x120, &x60); - secp256k1_scalar_sqr(&x126, &x112); - for (i = 0; i < 13; i++) { - secp256k1_scalar_sqr(&x126, &x126); + secp256k1_scalar_sqr(&x127, &x120); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x127, &x127); } - secp256k1_scalar_mul(&x126, &x126, &x14); + secp256k1_scalar_mul(&x127, &x127, &x7); - /* Then accumulate the final result (t starts at x126). */ - t = &x126; - for (i = 0; i < 3; i++) { + /* Then accumulate the final result (t starts at x127). */ + t = &x127; + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u5); /* 101 */ + secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 0 */ + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u5); /* 101 */ - for (i = 0; i < 5; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u11); /* 1011 */ - for (i = 0; i < 4; i++) { + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 3; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u11); /* 1011 */ + secp256k1_scalar_mul(t, t, &x2); /* 11 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } @@ -147,26 +134,38 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 6; i++) { /* 00 */ + for (i = 0; i < 4; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u13); /* 1101 */ - for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u5); /* 101 */ - for (i = 0; i < 3; i++) { + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ + secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u9); /* 1001 */ - for (i = 0; i < 6; i++) { /* 000 */ + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u5); /* 101 */ + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 10; i++) { /* 0000000 */ secp256k1_scalar_sqr(t, t); } @@ -179,34 +178,50 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u9); /* 1001 */ - for (i = 0; i < 6; i++) { /* 00 */ + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u11); /* 1011 */ - for (i = 0; i < 4; i++) { + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u13); /* 1101 */ - for (i = 0; i < 5; i++) { + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 4; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 6; i++) { /* 00 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 000000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u13); /* 1101 */ - for (i = 0; i < 10; i++) { /* 000000 */ + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u13); /* 1101 */ - for (i = 0; i < 4; i++) { + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &u9); /* 1001 */ + secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 6; i++) { /* 00000 */ secp256k1_scalar_sqr(t, t); } @@ -218,9 +233,9 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar } SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + /* d[0] is present and is the lowest word for all representations */ return !(a->d[0] & 1); } -#endif static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { #if defined(USE_SCALAR_INV_BUILTIN) @@ -244,18 +259,6 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_sc } #ifdef USE_ENDOMORPHISM -#if defined(EXHAUSTIVE_TEST_ORDER) -/** - * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the - * full case we don't bother making k1 and k2 be small, we just want them to be - * nontrivial to get full test coverage for the exhaustive tests. We therefore - * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. - */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; - *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; -} -#else /** * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, @@ -328,6 +331,5 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar secp256k1_scalar_add(r1, r1, a); } #endif -#endif -#endif /* SECP256K1_SCALAR_IMPL_H */ +#endif diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index 7e3ad572..fb8b882f 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -17,7 +17,6 @@ #include "ecdsa_impl.h" #include "eckey_impl.h" #include "hash_impl.h" -#include "scratch_impl.h" #define ARG_CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ @@ -115,24 +114,13 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } -secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t init_size, size_t max_size) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(max_size >= init_size); - - return secp256k1_scratch_create(&ctx->error_callback, init_size, max_size); -} - -void secp256k1_scratch_space_destroy(secp256k1_scratch_space* scratch) { - secp256k1_scratch_destroy(scratch); -} - static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { if (sizeof(secp256k1_ge_storage) == 64) { /* When the secp256k1_ge_storage type is exactly 64 byte, use its * representation inside secp256k1_pubkey, as conversion is very fast. * Note that secp256k1_pubkey_save must use the same representation. */ secp256k1_ge_storage s; - memcpy(&s, &pubkey->data[0], sizeof(s)); + memcpy(&s, &pubkey->data[0], 64); secp256k1_ge_from_storage(ge, &s); } else { /* Otherwise, fall back to 32-byte big endian for X and Y. */ @@ -149,7 +137,7 @@ static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { if (sizeof(secp256k1_ge_storage) == 64) { secp256k1_ge_storage s; secp256k1_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, sizeof(s)); + memcpy(&pubkey->data[0], &s, 64); } else { VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); secp256k1_fe_normalize_var(&ge->x); @@ -319,15 +307,10 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); } -static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { - memcpy(buf + *offset, data, len); - *offset += len; -} - static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { unsigned char keydata[112]; - unsigned int offset = 0; - secp256k1_rfc6979_hmac_sha256 rng; + int keylen = 64; + secp256k1_rfc6979_hmac_sha256_t rng; unsigned int i; /* We feed a byte array to the PRNG as input, consisting of: * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. @@ -337,15 +320,17 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m * different argument mixtures to emulate each other and result in the same * nonces. */ - buffer_append(keydata, &offset, key32, 32); - buffer_append(keydata, &offset, msg32, 32); + memcpy(keydata, key32, 32); + memcpy(keydata + 32, msg32, 32); if (data != NULL) { - buffer_append(keydata, &offset, data, 32); + memcpy(keydata + 64, data, 32); + keylen = 96; } if (algo16 != NULL) { - buffer_append(keydata, &offset, algo16, 16); + memcpy(keydata + keylen, algo16, 16); + keylen += 16; } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); memset(keydata, 0, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); @@ -439,33 +424,6 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p return ret; } -int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { - secp256k1_scalar sec; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, NULL); - secp256k1_scalar_negate(&sec, &sec); - secp256k1_scalar_get_b32(seckey, &sec); - - return 1; -} - -int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { - int ret = 0; - secp256k1_ge p; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - - ret = secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - secp256k1_ge_neg(&p, &p); - secp256k1_pubkey_save(pubkey, &p); - } - return ret; -} - int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { secp256k1_scalar term; secp256k1_scalar sec; @@ -594,6 +552,10 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey * # include "modules/ecdh/main_impl.h" #endif +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/main_impl.h" +#endif + #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/main_impl.h" #endif diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h index f1f9be07..f8efa93c 100644 --- a/src/secp256k1/src/testrand.h +++ b/src/secp256k1/src/testrand.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_TESTRAND_H -#define SECP256K1_TESTRAND_H +#ifndef _SECP256K1_TESTRAND_H_ +#define _SECP256K1_TESTRAND_H_ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -35,4 +35,4 @@ static void secp256k1_rand256_test(unsigned char *b32); /** Generate pseudorandom bytes with long sequences of zero and one bits. */ static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); -#endif /* SECP256K1_TESTRAND_H */ +#endif diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h index 30a91e52..15c7b9f1 100644 --- a/src/secp256k1/src/testrand_impl.h +++ b/src/secp256k1/src/testrand_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_TESTRAND_IMPL_H -#define SECP256K1_TESTRAND_IMPL_H +#ifndef _SECP256K1_TESTRAND_IMPL_H_ +#define _SECP256K1_TESTRAND_IMPL_H_ #include #include @@ -13,7 +13,7 @@ #include "testrand.h" #include "hash.h" -static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng; +static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; static uint32_t secp256k1_test_rng_precomputed[8]; static int secp256k1_test_rng_precomputed_used = 8; static uint64_t secp256k1_test_rng_integer; @@ -107,4 +107,4 @@ static void secp256k1_rand256_test(unsigned char *b32) { secp256k1_rand_bytes_test(b32, 32); } -#endif /* SECP256K1_TESTRAND_IMPL_H */ +#endif diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 893d2972..15982da8 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -10,7 +10,6 @@ #include #include -#include #include @@ -24,7 +23,7 @@ #include "openssl/ecdsa.h" #include "openssl/obj_mac.h" # if OPENSSL_VERSION_NUMBER < 0x10100000L -void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {*pr = sig->r; *ps = sig->s;} +# define ECDSA_SIG_get0(sig, _r, _s) *(_r) = sig->r; *(_s) = sig->s # endif #endif @@ -139,7 +138,6 @@ void random_scalar_order(secp256k1_scalar *num) { void run_context_tests(void) { secp256k1_pubkey pubkey; - secp256k1_pubkey zero_pubkey; secp256k1_ecdsa_signature sig; unsigned char ctmp[32]; int32_t ecount; @@ -154,8 +152,6 @@ void run_context_tests(void) { secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; - memset(&zero_pubkey, 0, sizeof(zero_pubkey)); - ecount = 0; ecount2 = 10; secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); @@ -208,20 +204,12 @@ void run_context_tests(void) { CHECK(ecount == 2); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0); - CHECK(ecount2 == 14); - CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0); - CHECK(ecount == 3); CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); - CHECK(ecount == 3); + CHECK(ecount == 2); CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); - CHECK(ecount == 4); + CHECK(ecount == 3); CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 14); + CHECK(ecount2 == 13); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, NULL); @@ -251,41 +239,6 @@ void run_context_tests(void) { secp256k1_context_destroy(NULL); } -void run_scratch_tests(void) { - int32_t ecount = 0; - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_scratch_space *scratch; - - /* Test public API */ - secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); - scratch = secp256k1_scratch_space_create(none, 100, 10); - CHECK(scratch == NULL); - CHECK(ecount == 1); - - scratch = secp256k1_scratch_space_create(none, 100, 100); - CHECK(scratch != NULL); - CHECK(ecount == 1); - secp256k1_scratch_space_destroy(scratch); - - scratch = secp256k1_scratch_space_create(none, 100, 1000); - CHECK(scratch != NULL); - CHECK(ecount == 1); - - /* Test internal API */ - CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); - CHECK(secp256k1_scratch_max_allocation(scratch, 1) < 1000); - CHECK(secp256k1_scratch_resize(scratch, 50, 1) == 1); /* no-op */ - CHECK(secp256k1_scratch_resize(scratch, 200, 1) == 1); - CHECK(secp256k1_scratch_resize(scratch, 950, 1) == 1); - CHECK(secp256k1_scratch_resize(scratch, 1000, 1) == 0); - CHECK(secp256k1_scratch_resize(scratch, 2000, 1) == 0); - CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); - - /* cleanup */ - secp256k1_scratch_space_destroy(scratch); - secp256k1_context_destroy(none); -} - /***** HASH TESTS *****/ void run_sha256_tests(void) { @@ -308,7 +261,7 @@ void run_sha256_tests(void) { int i; for (i = 0; i < 8; i++) { unsigned char out[32]; - secp256k1_sha256 hasher; + secp256k1_sha256_t hasher; secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_sha256_finalize(&hasher, out); @@ -351,7 +304,7 @@ void run_hmac_sha256_tests(void) { }; int i; for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256 hasher; + secp256k1_hmac_sha256_t hasher; unsigned char out[32]; secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); @@ -383,7 +336,7 @@ void run_rfc6979_hmac_sha256_tests(void) { {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} }; - secp256k1_rfc6979_hmac_sha256 rng; + secp256k1_rfc6979_hmac_sha256_t rng; unsigned char out[32]; int i; @@ -1929,9 +1882,9 @@ void test_ge(void) { * * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. */ - secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe zf; secp256k1_fe zfi2, zfi3; @@ -1969,7 +1922,7 @@ void test_ge(void) { /* Compute z inverses. */ { - secp256k1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); for (i = 0; i < 4 * runs + 1; i++) { if (i == 0) { /* The point at infinity does not have a meaningful z inverse. Any should do. */ @@ -2070,7 +2023,7 @@ void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); + secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } @@ -2091,9 +2044,9 @@ void test_ge(void) { /* Test batch gej -> ge conversion with and without known z ratios. */ { - secp256k1_fe *zr = (secp256k1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); + secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); for (i = 0; i < 4 * runs + 1; i++) { /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ if (i < 4 * runs) { @@ -2525,395 +2478,6 @@ void run_ecmult_const_tests(void) { ecmult_const_chain_multiply(); } -typedef struct { - secp256k1_scalar *sc; - secp256k1_ge *pt; -} ecmult_multi_data; - -static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - ecmult_multi_data *data = (ecmult_multi_data*) cbdata; - *sc = data->sc[idx]; - *pt = data->pt[idx]; - return 1; -} - -static int ecmult_multi_false_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - (void)sc; - (void)pt; - (void)idx; - (void)cbdata; - return 0; -} - -void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func ecmult_multi) { - int ncount; - secp256k1_scalar szero; - secp256k1_scalar sc[32]; - secp256k1_ge pt[32]; - secp256k1_gej r; - secp256k1_gej r2; - ecmult_multi_data data; - secp256k1_scratch *scratch_empty; - - data.sc = sc; - data.pt = pt; - secp256k1_scalar_set_int(&szero, 0); - secp256k1_scratch_reset(scratch); - - /* No points to multiply */ - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0)); - - /* Check 1- and 2-point multiplies against ecmult */ - for (ncount = 0; ncount < count; ncount++) { - secp256k1_ge ptg; - secp256k1_gej ptgj; - random_scalar_order(&sc[0]); - random_scalar_order(&sc[1]); - - random_group_element_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - pt[0] = ptg; - pt[1] = secp256k1_ge_const_g; - - /* only G scalar */ - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - - /* 1-point */ - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - - /* Try to multiply 1 point, but scratch space is empty */ - scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0, 0); - CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); - secp256k1_scratch_destroy(scratch_empty); - - /* Try to multiply 1 point, but callback returns false */ - CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1)); - - /* 2-point */ - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - - /* 2-point with G scalar */ - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - /* Check infinite outputs of various forms */ - for (ncount = 0; ncount < count; ncount++) { - secp256k1_ge ptg; - size_t i, j; - size_t sizes[] = { 2, 10, 32 }; - - for (j = 0; j < 3; j++) { - for (i = 0; i < 32; i++) { - random_scalar_order(&sc[i]); - secp256k1_ge_set_infinity(&pt[i]); - } - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - for (j = 0; j < 3; j++) { - for (i = 0; i < 32; i++) { - random_group_element_test(&ptg); - pt[i] = ptg; - secp256k1_scalar_set_int(&sc[i], 0); - } - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - for (j = 0; j < 3; j++) { - random_group_element_test(&ptg); - for (i = 0; i < 16; i++) { - random_scalar_order(&sc[2*i]); - secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]); - pt[2 * i] = ptg; - pt[2 * i + 1] = ptg; - } - - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - - random_scalar_order(&sc[0]); - for (i = 0; i < 16; i++) { - random_group_element_test(&ptg); - - sc[2*i] = sc[0]; - sc[2*i+1] = sc[0]; - pt[2 * i] = ptg; - secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]); - } - - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - random_group_element_test(&ptg); - secp256k1_scalar_set_int(&sc[0], 0); - pt[0] = ptg; - for (i = 1; i < 32; i++) { - pt[i] = ptg; - - random_scalar_order(&sc[i]); - secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]); - secp256k1_scalar_negate(&sc[i], &sc[i]); - } - - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32)); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - /* Check random points, constant scalar */ - for (ncount = 0; ncount < count; ncount++) { - size_t i; - secp256k1_gej_set_infinity(&r); - - random_scalar_order(&sc[0]); - for (i = 0; i < 20; i++) { - secp256k1_ge ptg; - sc[i] = sc[0]; - random_group_element_test(&ptg); - pt[i] = ptg; - secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); - } - - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - /* Check random scalars, constant point */ - for (ncount = 0; ncount < count; ncount++) { - size_t i; - secp256k1_ge ptg; - secp256k1_gej p0j; - secp256k1_scalar rs; - secp256k1_scalar_set_int(&rs, 0); - - random_group_element_test(&ptg); - for (i = 0; i < 20; i++) { - random_scalar_order(&sc[i]); - pt[i] = ptg; - secp256k1_scalar_add(&rs, &rs, &sc[i]); - } - - secp256k1_gej_set_ge(&p0j, &pt[0]); - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); - secp256k1_gej_neg(&r2, &r2); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - /* Sanity check that zero scalars don't cause problems */ - secp256k1_scalar_clear(&sc[0]); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); - secp256k1_scalar_clear(&sc[1]); - secp256k1_scalar_clear(&sc[2]); - secp256k1_scalar_clear(&sc[3]); - secp256k1_scalar_clear(&sc[4]); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6)); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5)); - CHECK(secp256k1_gej_is_infinity(&r)); - - /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ - { - const size_t TOP = 8; - size_t s0i, s1i; - size_t t0i, t1i; - secp256k1_ge ptg; - secp256k1_gej ptgj; - - random_group_element_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - - for(t0i = 0; t0i < TOP; t0i++) { - for(t1i = 0; t1i < TOP; t1i++) { - secp256k1_gej t0p, t1p; - secp256k1_scalar t0, t1; - - secp256k1_scalar_set_int(&t0, (t0i + 1) / 2); - secp256k1_scalar_cond_negate(&t0, t0i & 1); - secp256k1_scalar_set_int(&t1, (t1i + 1) / 2); - secp256k1_scalar_cond_negate(&t1, t1i & 1); - - secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero); - secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero); - - for(s0i = 0; s0i < TOP; s0i++) { - for(s1i = 0; s1i < TOP; s1i++) { - secp256k1_scalar tmp1, tmp2; - secp256k1_gej expected, actual; - - secp256k1_ge_set_gej(&pt[0], &t0p); - secp256k1_ge_set_gej(&pt[1], &t1p); - - secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2); - secp256k1_scalar_cond_negate(&sc[0], s0i & 1); - secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2); - secp256k1_scalar_cond_negate(&sc[1], s1i & 1); - - secp256k1_scalar_mul(&tmp1, &t0, &sc[0]); - secp256k1_scalar_mul(&tmp2, &t1, &sc[1]); - secp256k1_scalar_add(&tmp1, &tmp1, &tmp2); - - secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero); - CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2)); - secp256k1_gej_neg(&expected, &expected); - secp256k1_gej_add_var(&actual, &actual, &expected, NULL); - CHECK(secp256k1_gej_is_infinity(&actual)); - } - } - } - } - } -} - -void test_secp256k1_pippenger_bucket_window_inv(void) { - int i; - - CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0); - for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { -#ifdef USE_ENDOMORPHISM - /* Bucket_window of 8 is not used with endo */ - if (i == 8) { - continue; - } -#endif - CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i); - if (i != PIPPENGER_MAX_BUCKET_WINDOW) { - CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i); - } - } -} - -/** - * Probabilistically test the function returning the maximum number of possible points - * for a given scratch space. - */ -void test_ecmult_multi_pippenger_max_points(void) { - size_t scratch_size = secp256k1_rand_int(256); - size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); - secp256k1_scratch *scratch; - size_t n_points_supported; - int bucket_window = 0; - - for(; scratch_size < max_size; scratch_size+=256) { - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size); - CHECK(scratch != NULL); - n_points_supported = secp256k1_pippenger_max_points(scratch); - if (n_points_supported == 0) { - secp256k1_scratch_destroy(scratch); - continue; - } - bucket_window = secp256k1_pippenger_bucket_window(n_points_supported); - CHECK(secp256k1_scratch_resize(scratch, secp256k1_pippenger_scratch_size(n_points_supported, bucket_window), PIPPENGER_SCRATCH_OBJECTS)); - secp256k1_scratch_destroy(scratch); - } - CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW); -} - -/** - * Run secp256k1_ecmult_multi_var with num points and a scratch space restricted to - * 1 <= i <= num points. - */ -void test_ecmult_multi_batching(void) { - static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; - secp256k1_scalar scG; - secp256k1_scalar szero; - secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_scalar) * n_points); - secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * n_points); - secp256k1_gej r; - secp256k1_gej r2; - ecmult_multi_data data; - int i; - secp256k1_scratch *scratch; - - secp256k1_gej_set_infinity(&r2); - secp256k1_scalar_set_int(&szero, 0); - - /* Get random scalars and group elements and compute result */ - random_scalar_order(&scG); - secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG); - for(i = 0; i < n_points; i++) { - secp256k1_ge ptg; - secp256k1_gej ptgj; - random_group_element_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - pt[i] = ptg; - random_scalar_order(&sc[i]); - secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL); - secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL); - } - data.sc = sc; - data.pt = pt; - - /* Test with empty scratch space */ - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, 0); - CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1)); - secp256k1_scratch_destroy(scratch); - - /* Test with space for 1 point in pippenger. That's not enough because - * ecmult_multi selects strauss which requires more memory. */ - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); - CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1)); - secp256k1_scratch_destroy(scratch); - - secp256k1_gej_neg(&r2, &r2); - for(i = 1; i <= n_points; i++) { - if (i > ECMULT_PIPPENGER_THRESHOLD) { - int bucket_window = secp256k1_pippenger_bucket_window(i); - size_t scratch_size = secp256k1_pippenger_scratch_size(i, bucket_window); - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); - } else { - size_t scratch_size = secp256k1_strauss_scratch_size(i); - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); - } - CHECK(secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - secp256k1_scratch_destroy(scratch); - } - free(sc); - free(pt); -} - -void run_ecmult_multi_tests(void) { - secp256k1_scratch *scratch; - - test_secp256k1_pippenger_bucket_window_inv(); - test_ecmult_multi_pippenger_max_points(); - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, 819200); - test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); - test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single); - test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single); - secp256k1_scratch_destroy(scratch); - - /* Run test_ecmult_multi with space for exactly one point */ - scratch = secp256k1_scratch_create(&ctx->error_callback, 0, secp256k1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); - test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); - secp256k1_scratch_destroy(scratch); - - test_ecmult_multi_batching(); -} - void test_wnaf(const secp256k1_scalar *number, int w) { secp256k1_scalar x, two, t; int wnaf[256]; @@ -3002,61 +2566,6 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) { CHECK(secp256k1_scalar_eq(&x, &num)); } -void test_fixed_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, shift; - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num = *number; - - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&shift, 1 << w); - /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ -#ifdef USE_ENDOMORPHISM - for (i = 0; i < 16; ++i) { - secp256k1_scalar_shr_int(&num, 8); - } -#endif - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - - for (i = WNAF_SIZE(w)-1; i >= 0; --i) { - secp256k1_scalar t; - int v = wnaf[i]; - CHECK(v != 0); /* check nonzero */ - CHECK(v & 1); /* check parity */ - CHECK(v > -(1 << w)); /* check range above */ - CHECK(v < (1 << w)); /* check range below */ - - secp256k1_scalar_mul(&x, &x, &shift); - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - /* If skew is 1 then add 1 to num */ - secp256k1_scalar_cadd_bit(&num, 0, skew == 1); - CHECK(secp256k1_scalar_eq(&x, &num)); -} - -void test_fixed_wnaf_zero(int w) { - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num; - - secp256k1_scalar_set_int(&num, 0); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - - for (i = WNAF_SIZE(w)-1; i >= 0; --i) { - int v = wnaf[i]; - CHECK(v == 0); - } - CHECK(skew == 0); -} - void run_wnaf(void) { int i; secp256k1_scalar n = {{0}}; @@ -3067,15 +2576,12 @@ void run_wnaf(void) { test_constant_wnaf(&n, 4); n.d[0] = 2; test_constant_wnaf(&n, 4); - /* Test 0 */ - test_fixed_wnaf_zero(4); /* Random tests */ for (i = 0; i < count; i++) { random_scalar_order(&n); test_wnaf(&n, 4+(i%10)); test_constant_wnaf_negate(&n); test_constant_wnaf(&n, 4 + (i % 10)); - test_fixed_wnaf(&n, 4 + (i % 10)); } secp256k1_scalar_set_int(&n, 0); CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); @@ -3662,7 +3168,7 @@ void run_eckey_edge_case_test(void) { VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); pubkey_negone = pubkey; - /* Tweak of zero leaves the value unchanged. */ + /* Tweak of zero leaves the value changed. */ memset(ctmp2, 0, 32); CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); @@ -3933,7 +3439,6 @@ void test_ecdsa_end_to_end(void) { unsigned char pubkeyc[65]; size_t pubkeyclen = 65; secp256k1_pubkey pubkey; - secp256k1_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; @@ -3955,13 +3460,6 @@ void test_ecdsa_end_to_end(void) { memset(&pubkey, 0, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); - /* Verify negation changes the key and changes it back */ - memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); - CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); - CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); - CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); - /* Verify private key import and export. */ CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); @@ -4890,6 +4388,10 @@ void run_ecdsa_openssl(void) { # include "modules/ecdh/tests_impl.h" #endif +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/tests_impl.h" +#endif + #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif @@ -4918,7 +4420,7 @@ int main(int argc, char **argv) { } } else { FILE *frand = fopen("/dev/urandom", "r"); - if ((frand == NULL) || fread(&seed16, sizeof(seed16), 1, frand) != sizeof(seed16)) { + if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { uint64_t t = time(NULL) * (uint64_t)1337; seed16[0] ^= t; seed16[1] ^= t >> 8; @@ -4929,9 +4431,7 @@ int main(int argc, char **argv) { seed16[6] ^= t >> 48; seed16[7] ^= t >> 56; } - if (frand) { - fclose(frand); - } + fclose(frand); } secp256k1_rand_seed(seed16); @@ -4940,7 +4440,6 @@ int main(int argc, char **argv) { /* initialize */ run_context_tests(); - run_scratch_tests(); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); if (secp256k1_rand_bits(1)) { secp256k1_rand256(run32); @@ -4982,7 +4481,6 @@ int main(int argc, char **argv) { run_ecmult_constants(); run_ecmult_gen_blind(); run_ecmult_const_tests(); - run_ecmult_multi_tests(); run_ec_combine(); /* endomorphism tests */ @@ -5011,6 +4509,11 @@ int main(int argc, char **argv) { run_ecdsa_openssl(); #endif +#ifdef ENABLE_MODULE_SCHNORR + /* Schnorr tests */ + run_schnorr_tests(); +#endif + #ifdef ENABLE_MODULE_RECOVERY /* ECDSA pubkey recovery tests */ run_recovery_tests(); diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index e0147500..4eef4ded 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef SECP256K1_UTIL_H -#define SECP256K1_UTIL_H +#ifndef _SECP256K1_UTIL_H_ +#define _SECP256K1_UTIL_H_ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -57,10 +57,7 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * #endif /* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#if defined(COVERAGE) -#define VERIFY_CHECK(check) -#define VERIFY_SETUP(stmt) -#elif defined(VERIFY) +#ifdef VERIFY #define VERIFY_CHECK CHECK #define VERIFY_SETUP(stmt) do { stmt; } while(0) #else @@ -76,14 +73,6 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ return ret; } -static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void *ptr, size_t size) { - void *ret = realloc(ptr, size); - if (ret == NULL) { - secp256k1_callback_call(cb, "Out of memory"); - } - return ret; -} - /* Macro for restrict, when available and not in a VERIFY build. */ #if defined(SECP256K1_BUILD) && defined(VERIFY) # define SECP256K1_RESTRICT @@ -118,4 +107,4 @@ static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; #endif -#endif /* SECP256K1_UTIL_H */ +#endif From 335e6cfa2f59f29d0ab3bcab1c51860ae9fce150 Mon Sep 17 00:00:00 2001 From: Michael Bos Date: Thu, 12 Mar 2020 10:31:02 +0100 Subject: [PATCH 4/4] Adapted src --- src/secp256k1/src/bench_ecmult.c | 196 ---------- src/secp256k1/src/scalar_low.h | 15 - src/secp256k1/src/scalar_low_impl.h | 114 ------ src/secp256k1/src/scratch.h | 35 -- src/secp256k1/src/scratch_impl.h | 77 ---- src/secp256k1/src/tests_exhaustive.c | 511 --------------------------- 6 files changed, 948 deletions(-) delete mode 100644 src/secp256k1/src/bench_ecmult.c delete mode 100644 src/secp256k1/src/scalar_low.h delete mode 100644 src/secp256k1/src/scalar_low_impl.h delete mode 100644 src/secp256k1/src/scratch.h delete mode 100644 src/secp256k1/src/scratch_impl.h delete mode 100644 src/secp256k1/src/tests_exhaustive.c diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c deleted file mode 100644 index 3a7bfe37..00000000 --- a/src/secp256k1/src/bench_ecmult.c +++ /dev/null @@ -1,196 +0,0 @@ -/********************************************************************** - * Copyright (c) 2017 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ -#include - -#include "include/secp256k1.h" - -#include "util.h" -#include "hash_impl.h" -#include "num_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_impl.h" -#include "bench.h" -#include "secp256k1.c" - -#define POINTS 32768 -#define ITERS 10000 - -typedef struct { - /* Setup once in advance */ - secp256k1_context* ctx; - secp256k1_scratch_space* scratch; - secp256k1_scalar* scalars; - secp256k1_ge* pubkeys; - secp256k1_scalar* seckeys; - secp256k1_gej* expected_output; - secp256k1_ecmult_multi_func ecmult_multi; - - /* Changes per test */ - size_t count; - int includes_g; - - /* Changes per test iteration */ - size_t offset1; - size_t offset2; - - /* Test output. */ - secp256k1_gej* output; -} bench_data; - -static int bench_callback(secp256k1_scalar* sc, secp256k1_ge* ge, size_t idx, void* arg) { - bench_data* data = (bench_data*)arg; - if (data->includes_g) ++idx; - if (idx == 0) { - *sc = data->scalars[data->offset1]; - *ge = secp256k1_ge_const_g; - } else { - *sc = data->scalars[(data->offset1 + idx) % POINTS]; - *ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS]; - } - return 1; -} - -static void bench_ecmult(void* arg) { - bench_data* data = (bench_data*)arg; - - size_t count = data->count; - int includes_g = data->includes_g; - size_t iters = 1 + ITERS / count; - size_t iter; - - for (iter = 0; iter < iters; ++iter) { - data->ecmult_multi(&data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_callback, arg, count - includes_g); - data->offset1 = (data->offset1 + count) % POINTS; - data->offset2 = (data->offset2 + count - 1) % POINTS; - } -} - -static void bench_ecmult_setup(void* arg) { - bench_data* data = (bench_data*)arg; - data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS; - data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS; -} - -static void bench_ecmult_teardown(void* arg) { - bench_data* data = (bench_data*)arg; - size_t iters = 1 + ITERS / data->count; - size_t iter; - /* Verify the results in teardown, to avoid doing comparisons while benchmarking. */ - for (iter = 0; iter < iters; ++iter) { - secp256k1_gej tmp; - secp256k1_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); - CHECK(secp256k1_gej_is_infinity(&tmp)); - } -} - -static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { - secp256k1_sha256 sha256; - unsigned char c[11] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0}; - unsigned char buf[32]; - int overflow = 0; - c[6] = num; - c[7] = num >> 8; - c[8] = num >> 16; - c[9] = num >> 24; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, c, sizeof(c)); - secp256k1_sha256_finalize(&sha256, buf); - secp256k1_scalar_set_b32(scalar, buf, &overflow); - CHECK(!overflow); -} - -static void run_test(bench_data* data, size_t count, int includes_g) { - char str[32]; - static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - size_t iters = 1 + ITERS / count; - size_t iter; - - data->count = count; - data->includes_g = includes_g; - - /* Compute (the negation of) the expected results directly. */ - data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS; - data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS; - for (iter = 0; iter < iters; ++iter) { - secp256k1_scalar tmp; - secp256k1_scalar total = data->scalars[(data->offset1++) % POINTS]; - size_t i = 0; - for (i = 0; i + 1 < count; ++i) { - secp256k1_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); - secp256k1_scalar_add(&total, &total, &tmp); - } - secp256k1_scalar_negate(&total, &total); - secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total); - } - - /* Run the benchmark. */ - sprintf(str, includes_g ? "ecmult_%ig" : "ecmult_%i", (int)count); - run_benchmark(str, bench_ecmult, bench_ecmult_setup, bench_ecmult_teardown, data, 10, count * (1 + ITERS / count)); -} - -int main(int argc, char **argv) { - bench_data data; - int i, p; - secp256k1_gej* pubkeys_gej; - size_t scratch_size; - - if (argc > 1) { - if(have_flag(argc, argv, "pippenger_wnaf")) { - printf("Using pippenger_wnaf:\n"); - data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single; - } else if(have_flag(argc, argv, "strauss_wnaf")) { - printf("Using strauss_wnaf:\n"); - data.ecmult_multi = secp256k1_ecmult_strauss_batch_single; - } - } else { - data.ecmult_multi = secp256k1_ecmult_multi_var; - } - - /* Allocate stuff */ - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; - data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size, scratch_size); - data.scalars = malloc(sizeof(secp256k1_scalar) * POINTS); - data.seckeys = malloc(sizeof(secp256k1_scalar) * POINTS); - data.pubkeys = malloc(sizeof(secp256k1_ge) * POINTS); - data.expected_output = malloc(sizeof(secp256k1_gej) * (ITERS + 1)); - data.output = malloc(sizeof(secp256k1_gej) * (ITERS + 1)); - - /* Generate a set of scalars, and private/public keypairs. */ - pubkeys_gej = malloc(sizeof(secp256k1_gej) * POINTS); - secp256k1_gej_set_ge(&pubkeys_gej[0], &secp256k1_ge_const_g); - secp256k1_scalar_set_int(&data.seckeys[0], 1); - for (i = 0; i < POINTS; ++i) { - generate_scalar(i, &data.scalars[i]); - if (i) { - secp256k1_gej_double_var(&pubkeys_gej[i], &pubkeys_gej[i - 1], NULL); - secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); - } - } - secp256k1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS, &data.ctx->error_callback); - free(pubkeys_gej); - - for (i = 1; i <= 8; ++i) { - run_test(&data, i, 1); - } - - for (p = 0; p <= 11; ++p) { - for (i = 9; i <= 16; ++i) { - run_test(&data, i << p, 1); - } - } - secp256k1_context_destroy(data.ctx); - secp256k1_scratch_space_destroy(data.scratch); - free(data.scalars); - free(data.pubkeys); - free(data.seckeys); - free(data.output); - free(data.expected_output); - - return(0); -} diff --git a/src/secp256k1/src/scalar_low.h b/src/secp256k1/src/scalar_low.h deleted file mode 100644 index 5836febc..00000000 --- a/src/secp256k1/src/scalar_low.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef uint32_t secp256k1_scalar; - -#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_low_impl.h b/src/secp256k1/src/scalar_low_impl.h deleted file mode 100644 index c80e70c5..00000000 --- a/src/secp256k1/src/scalar_low_impl.h +++ /dev/null @@ -1,114 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H - -#include "scalar.h" - -#include - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - return !(*a & 1); -} - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - if (offset < 32) - return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); - else - return 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - return secp256k1_scalar_get_bits(a, offset, count); -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; - return *r < *b; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - if (flag && bit < 32) - *r += (1 << bit); -#ifdef VERIFY - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; - int i; - *r = 0; - for (i = 0; i < 32; i++) { - *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; - } - /* just deny overflow, it basically always happens */ - if (overflow) *overflow = 0; -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - memset(bin, 0, 32); - bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return *a == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - if (*a == 0) { - *r = 0; - } else { - *r = EXHAUSTIVE_TEST_ORDER - *a; - } -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return *a == 1; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - return *a > EXHAUSTIVE_TEST_ORDER / 2; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - if (flag) secp256k1_scalar_negate(r, r); - return flag ? -1 : 1; -} - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = *r & ((1 << n) - 1); - *r >>= n; - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r1 = *a; - *r2 = 0; -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return *a == *b; -} - -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h deleted file mode 100644 index aba56e21..00000000 --- a/src/secp256k1/src/scratch.h +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************** - * Copyright (c) 2017 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCRATCH_ -#define _SECP256K1_SCRATCH_ - -/* The typedef is used internally; the struct name is used in the public API - * (where it is exposed as a different typedef) */ -typedef struct secp256k1_scratch_space_struct { - void *data; - size_t offset; - size_t init_size; - size_t max_size; - const secp256k1_callback* error_callback; -} secp256k1_scratch; - -static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size); -static void secp256k1_scratch_destroy(secp256k1_scratch* scratch); - -/** Returns the maximum allocation the scratch space will allow */ -static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t n_objects); - -/** Attempts to allocate so that there are `n` available bytes. Returns 1 on success, 0 on failure */ -static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t n_objects); - -/** Returns a pointer into the scratch space or NULL if there is insufficient available space */ -static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t n); - -/** Resets the returned pointer to the beginning of space */ -static void secp256k1_scratch_reset(secp256k1_scratch* scratch); - -#endif diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h deleted file mode 100644 index 9bd68fe1..00000000 --- a/src/secp256k1/src/scratch_impl.h +++ /dev/null @@ -1,77 +0,0 @@ -/********************************************************************** - * Copyright (c) 2017 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCRATCH_IMPL_H_ -#define _SECP256K1_SCRATCH_IMPL_H_ - -#include "scratch.h" - -/* Using 16 bytes alignment because common architectures never have alignment - * requirements above 8 for any of the types we care about. In addition we - * leave some room because currently we don't care about a few bytes. - * TODO: Determine this at configure time. */ -#define ALIGNMENT 16 - -static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size) { - secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret)); - if (ret != NULL) { - ret->data = checked_malloc(error_callback, init_size); - if (ret->data == NULL) { - free (ret); - return NULL; - } - ret->offset = 0; - ret->init_size = init_size; - ret->max_size = max_size; - ret->error_callback = error_callback; - } - return ret; -} - -static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) { - if (scratch != NULL) { - free(scratch->data); - free(scratch); - } -} - -static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) { - if (scratch->max_size <= objects * ALIGNMENT) { - return 0; - } - return scratch->max_size - objects * ALIGNMENT; -} - -static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t objects) { - n += objects * ALIGNMENT; - if (n > scratch->init_size && n <= scratch->max_size) { - void *tmp = checked_realloc(scratch->error_callback, scratch->data, n); - if (tmp == NULL) { - return 0; - } - scratch->init_size = n; - scratch->data = tmp; - } - return n <= scratch->max_size; -} - -static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) { - void *ret; - size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; - if (size + scratch->offset > scratch->init_size) { - return NULL; - } - ret = (void *) ((unsigned char *) scratch->data + scratch->offset); - memset(ret, 0, size); - scratch->offset += size; - return ret; -} - -static void secp256k1_scratch_reset(secp256k1_scratch* scratch) { - scratch->offset = 0; -} - -#endif diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c deleted file mode 100644 index 141645ea..00000000 --- a/src/secp256k1/src/tests_exhaustive.c +++ /dev/null @@ -1,511 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include - -#include - -#undef USE_ECMULT_STATIC_PRECOMPUTATION - -#ifndef EXHAUSTIVE_TEST_ORDER -/* see group_impl.h for allowable values */ -#define EXHAUSTIVE_TEST_ORDER 13 -#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ -#endif - -#include "include/secp256k1.h" -#include "group.h" -#include "secp256k1.c" -#include "testrand_impl.h" - -#ifdef ENABLE_MODULE_RECOVERY -#include "src/modules/recovery/main_impl.h" -#include "include/secp256k1_recovery.h" -#endif - -/** stolen from tests.c */ -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); - CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); -} - -void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; secp256k1_fe_normalize_weak(&u2); - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; secp256k1_fe_normalize_weak(&s2); - CHECK(secp256k1_fe_equal_var(&u1, &u2)); - CHECK(secp256k1_fe_equal_var(&s1, &s2)); -} - -void random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} -/** END stolen from tests.c */ - -int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, - const unsigned char *key32, const unsigned char *algo16, - void *data, unsigned int attempt) { - secp256k1_scalar s; - int *idata = data; - (void)msg32; - (void)key32; - (void)algo16; - /* Some nonces cannot be used because they'd cause s and/or r to be zero. - * The signing function has retry logic here that just re-calls the nonce - * function with an increased `attempt`. So if attempt > 0 this means we - * need to change the nonce to avoid an infinite loop. */ - if (attempt > 0) { - *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; - } - secp256k1_scalar_set_int(&s, *idata); - secp256k1_scalar_get_b32(nonce32, &s); - return 1; -} - -#ifdef USE_ENDOMORPHISM -void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { - int i; - for (i = 0; i < order; i++) { - secp256k1_ge res; - secp256k1_ge_mul_lambda(&res, &group[i]); - ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); - } -} -#endif - -void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j; - - /* Sanity-check (and check infinity functions) */ - CHECK(secp256k1_ge_is_infinity(&group[0])); - CHECK(secp256k1_gej_is_infinity(&groupj[0])); - for (i = 1; i < order; i++) { - CHECK(!secp256k1_ge_is_infinity(&group[i])); - CHECK(!secp256k1_gej_is_infinity(&groupj[i])); - } - - /* Check all addition formulae */ - for (j = 0; j < order; j++) { - secp256k1_fe fe_inv; - secp256k1_fe_inv(&fe_inv, &groupj[j].z); - for (i = 0; i < order; i++) { - secp256k1_ge zless_gej; - secp256k1_gej tmp; - /* add_var */ - secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_ge */ - if (j > 0) { - secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - /* add_ge_var */ - secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_zinv_var */ - zless_gej.infinity = groupj[j].infinity; - zless_gej.x = groupj[j].x; - zless_gej.y = groupj[j].y; - secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - } - - /* Check doubling */ - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - if (i > 0) { - secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - secp256k1_gej_double_var(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - - /* Check negation */ - for (i = 1; i < order; i++) { - secp256k1_ge tmp; - secp256k1_gej tmpj; - secp256k1_ge_neg(&tmp, &group[i]); - ge_equals_ge(&group[order - i], &tmp); - secp256k1_gej_neg(&tmpj, &groupj[i]); - ge_equals_gej(&group[order - i], &tmpj); - } -} - -void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j, r_log; - for (r_log = 1; r_log < order; r_log++) { - for (j = 0; j < order; j++) { - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - secp256k1_scalar na, ng; - secp256k1_scalar_set_int(&na, i); - secp256k1_scalar_set_int(&ng, j); - - secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); - ge_equals_gej(&group[(i * r_log + j) % order], &tmp); - - if (i > 0) { - secp256k1_ecmult_const(&tmp, &group[i], &ng); - ge_equals_gej(&group[(i * j) % order], &tmp); - } - } - } - } -} - -typedef struct { - secp256k1_scalar sc[2]; - secp256k1_ge pt[2]; -} ecmult_multi_data; - -static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - ecmult_multi_data *data = (ecmult_multi_data*) cbdata; - *sc = data->sc[idx]; - *pt = data->pt[idx]; - return 1; -} - -void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k, x, y; - secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 1024, 4096); - for (i = 0; i < order; i++) { - for (j = 0; j < order; j++) { - for (k = 0; k < order; k++) { - for (x = 0; x < order; x++) { - for (y = 0; y < order; y++) { - secp256k1_gej tmp; - secp256k1_scalar g_sc; - ecmult_multi_data data; - - secp256k1_scalar_set_int(&data.sc[0], i); - secp256k1_scalar_set_int(&data.sc[1], j); - secp256k1_scalar_set_int(&g_sc, k); - data.pt[0] = group[x]; - data.pt[1] = group[y]; - - secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); - ge_equals_gej(&group[(i * x + j * y + k) % order], &tmp); - } - } - } - } - } - secp256k1_scratch_destroy(scratch); -} - -void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { - secp256k1_fe x; - unsigned char x_bin[32]; - k %= EXHAUSTIVE_TEST_ORDER; - x = group[k].x; - secp256k1_fe_normalize(&x); - secp256k1_fe_get_b32(x_bin, &x); - secp256k1_scalar_set_b32(r, x_bin, NULL); -} - -void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* Verify by calling verify */ - secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - secp256k1_scalar_get_b32(msg32, &msg_s); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} - -void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } - - /* We would like to verify zero-knowledge here by counting how often every - * possible (s, r) tuple appears, but because the group order is larger - * than the field order, when coercing the x-values to scalar values, some - * appear more often than others, so we are actually not zero-knowledge. - * (This effect also appears in the real code, but the difference is on the - * order of 1/2^128th the field order, so the deviation is not useful to a - * computationally bounded attacker.) - */ -} - -#ifdef ENABLE_MODULE_RECOVERY -void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_fe r_dot_y_normalized; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - int expected_recid; - int recid; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - /* Check directly */ - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - /* In computing the recid, there is an overflow condition that is disabled in - * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value - * will exceed the group order, and our signing code always holds out for r - * values that don't overflow, so with a proper overflow check the tests would - * loop indefinitely. */ - r_dot_y_normalized = group[k].y; - secp256k1_fe_normalize(&r_dot_y_normalized); - /* Also the recovery id is flipped depending if we hit the low-s branch */ - if ((k * s) % order == (i + r * j) % order) { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; - } else { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; - } - CHECK(recid == expected_recid); - - /* Convert to a standard sig then check */ - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } -} - -void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - /* This is essentially a copy of test_exhaustive_verify, with recovery added */ - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int recid = 0; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - secp256k1_scalar_get_b32(msg32, &msg_s); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* We would like to try recovering the pubkey and checking that it matches, - * but pubkey recovery is impossible in the exhaustive tests (the reason - * being that there are 12 nonzero r values, 12 nonzero points, and no - * overlap between the sets, so there are no valid signatures). */ - - /* Verify by converting to a standard signature and calling verify */ - secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} -#endif - -int main(void) { - int i; - secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; - secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; - - /* Build context */ - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - /* TODO set z = 1, then do num_tests runs with random z values */ - - /* Generate the entire group */ - secp256k1_gej_set_infinity(&groupj[0]); - secp256k1_ge_set_gej(&group[0], &groupj[0]); - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - /* Set a different random z-value for each Jacobian point */ - secp256k1_fe z; - random_fe(&z); - - secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); - secp256k1_ge_set_gej(&group[i], &groupj[i]); - secp256k1_gej_rescale(&groupj[i], &z); - - /* Verify against ecmult_gen */ - { - secp256k1_scalar scalar_i; - secp256k1_gej generatedj; - secp256k1_ge generated; - - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - secp256k1_ge_set_gej(&generated, &generatedj); - - CHECK(group[i].infinity == 0); - CHECK(generated.infinity == 0); - CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); - CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); - } - } - - /* Run the tests */ -#ifdef USE_ENDOMORPHISM - test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); -#endif - test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); - -#ifdef ENABLE_MODULE_RECOVERY - test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); -#endif - - secp256k1_context_destroy(ctx); - return 0; -} -