#include <stdlib.h>1#include <stdio.h>2#include <string.h>3#include <math.h>4#include <time.h>5#include "gmp.h"6#include "mpzutil.h"7#include "ffwrapper.h"8#include "ffpoly.h"9#include "hecurve.h"10#include "cstd.h"111213/*14Copyright 2007 Andrew V. Sutherland1516This file is part of smalljac.1718smalljac is free software: you can redistribute it and/or modify19it under the terms of the GNU General Public License as published by20the Free Software Foundation, either version 2 of the License, or21(at your option) any later version.2223smalljac is distributed in the hope that it will be useful,24but WITHOUT ANY WARRANTY; without even the implied warranty of25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the26GNU General Public License for more details.2728You should have received a copy of the GNU General Public License29along with GenericGroupDemo. If not, see <http://www.gnu.org/licenses/>.30*/3132#if HECURVE_GENUS == 33334#define _dbg_print_uv(s,u,v) if ( dbg_level >= DEBUG_LEVEL ) { printf (s); hecurve_print(u,v); }3536#define sub _ff_sub37#define subf _ff_subfrom38#define add _ff_add39#define addt _ff_addto40#define mult _ff_mult41#define multx(a,b) ff_mult(a,a,b)42#define sqr _ff_square43#define neg _ff_neg44#define dbl _ff_x24546// For simplicity, we assume no initilization of field elements is required. Debug code assume ff_t fits in an unsigned long.4748int hecurve_g3_compose (ff_t u[4], ff_t v[3], ff_t u1[4], ff_t v1[3], ff_t u2[4], ff_t v2[3], ff_t f[8], hecurve_ctx_t *ctx)49{50_ff_t_declare_reg d0, d1, d2, t0, w0, w1, w2, w3, w4, w5, w6, w7, r, x0, x1, x2;5152if ( ctx && ctx->state == 1 ) {53// get invert result and restore saved variables54_ff_set (w1, ctx->invert); // inverted value of r*s155_ff_set (r, ctx->r);56_ff_set (d0, ctx->s0);57_ff_set (d1, ctx->s1);58_ff_set (d2, ctx->s2);59/// dbg_printf ("Restored r = %lu, s2 = %lu, s1 = %lu, s0 = %lu, w1 = %lu\n", r, d2, d1, d0, w1);60goto hecurve_g3_compose_inverted;61}6263#if ! HECURVE_FAST64if ( dbg_level >= 2 ) {65printf ("Compose_3_3 inputs\n"); hecurve_print(u1,v1); hecurve_print(u2,v2);66}67#endif68#if HECURVE_VERIFY69if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_g3_compose: invalid input\n"); exit (0); }70if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_g3_compose: invalid input\n"); exit (0); }71#endif7273if ( ! _ff_one(u1[3]) || ! _ff_one(u2[3]) ) { hecurve_compose_cantor(u,v,u1,v1,u2,v2,f); return 1; }7475// 1. Compute r = Resultant(u1,u2)76sub(d0,u2[0],u1[0]); // d0 = u20-u1077sub(d1,u2[1],u1[1]); // d1 = u21-u1178sub(d2,u2[2],u1[2]); // d2 = u22-u1279mult(w1,u1[1],u2[0]); // w1 = t3 = u11u2080mult(t0,u1[0],u2[1]); // t0 = t4 = u10u2181subf(w1,t0); // w1 = t3-t482mult(w2,u1[2],u2[0]); // w2 = t5 = u12u2083mult(t0,u1[0],u2[2]); // t0 = t6 = u10u2284subf(w2,t0); // w2 = t5-t685mult(w3,u1[2],u2[1]); // w3 = t1 = u12u2186mult(t0,u1[1],u2[2]); // t0 = t2 = u11u2287subf(w3,t0); // w3 = t1-t288mult(w4,d1,d0); // w4 = t1189sqr(w5,d1); // w5 = t890mult(t0,d2,w1); // t0 = t991sqr(w6,d0); // w6 = t792subf(w6,t0); // w6 = t7-t993mult(w7,d2,w2); // w7 = t10 = (u22-u12)(t5-t6)94subf(w7,w4); // w7 = t10-t1195add(t0,d0,w3);96mult(r,t0,w6);97sub(t0,w7,w4);98multx(t0,w2);99addt(r,t0);100mult(t0,w5,w1);101addt(r,t0); // r = (d0+w3)w6+w2(w7-w4)+w5w1102/// dbg_printf ("r = %lu\n", r);103// if ( _ff_zero(r) ) { hecurve_compose_cantor(u,v,u1,v1,u2,v2,f); return 1; } // handled below104105// 2. Compute inv = r/u1 mod u2106add(t0,w3,d0); // t0 = t1-t2+u20-u10107mult(w1,t0,d2);108subf(w1,w5); // w1 = inv2 = (t1-t2+u20-u10)(u22-u12)-t8109mult(w2,u2[2],w1);110subf(w2,w7); // w2 = inv1 = inv2u22 -t10+t11111mult(t0,u2[2],w7);112addt(t0,w6); // t0 = u22(t10-t11)+t7-t9113mult(w3,w1,u2[1]);114subf(w3,t0); // w3 = inv0 = inv2u21 - (u22(t10-t11)+t7-t9)115/// dbg_printf ("inv = %lux^2 + %lux + %lu\n", w1, w2, w3);116117// 3. Compute s' = rs = (v2-v1)inv (mod u2) - note that we don't use Karatusba here since field mults aren't much slower than add/sub118sub(d0,v2[0],v1[0]); // do = v20-v10119sub(d1,v2[1],v1[1]); // d1 = v21-v11120sub(d2,v2[2],v1[2]); // d2 = v22-v12121mult(w5,d0,w3); // w5 = t15 = r'0122mult(w4,d2,w1); // w4 = t17 = r'4123mult(w6,d1,w3);124mult(t0,d0,w2);125addt(w6,t0); // w6 = r'1 = d1w3+d0w2126mult(w7,d1,w2);127mult(t0,d2,w3);128addt(w7,t0);129mult(t0,d0,w1);130addt(w7,t0); // w7 = r'2 = d1w2+d2w3+d0w1131mult(w3,d2,w2);132mult(t0,d1,w1);133addt(t0,w3);134mult(w3,u2[2],w4);135subf(w3,t0); // w3 = t18 = u22w4 - (d2w2+d1w2)136mult(w2,u2[0],w3); // w2 = t15 = u20w3137mult(w1,u2[1],w4); // w1 = t16 = u21w4138add(d0,w2,w5); // d0 = s'0 = w2+w5139add(d1,u2[0],u2[1]);140sub(t0,w4,w3);141multx(t0,d1);142sub(d1,w6,t0);143addt(d1,w1);144subf(d1,w2); // d1 = s'1 = w6 - (u20+u21)(w4-w3)+w1-w2145mult(d2,u2[2],w3);146subf(d2,w1);147addt(d2,w7); // d2 = s'2 = w7-w1+u22w3148/// dbg_printf ("s' = %lux^2 + %lux + %lu\n", d2, d1, d0);149150mult(t0,r,d2);151if ( _ff_zero(t0) ) {152int sts;153// check for squaring and inverse cases before resorting to Cantor - caller really should use hecurve_square154sts = hecurve_cmp (u1,v1,u2,v2);155if ( sts == 1 ) return hecurve_g3_square(u,v,u1,v1,f,ctx);156if ( sts == -1 ) { _hecurve_set_identity(u,v); return 1; }157hecurve_compose_cantor(u,v,u1,v1,u2,v2,f);158return 1;159}160if ( ctx && ! ctx->state ) {161_ff_set (ctx->s0, d0);162_ff_set (ctx->s1, d1);163_ff_set (ctx->s2, d2);164_ff_set (ctx->r, r);165_ff_set (ctx->invert, t0); // return to let caller invert166ctx->state = 1;167/// dbg_printf("Returning to let caller invert %lu\n", t0);168return 0;169}170_ff_invert(w1,t0);171172hecurve_g3_compose_inverted: // caller returns here after inverting173// we assume w1, r, d0, d1, and d2 are set, all others free174// 4. Compute s = s'/r and make monic175mult(w2,r,w1); // w2 = rw1 = 1/s2176sqr(w7,d2);177multx(w7,w1);178ff_negate(w7); // w7 = -s2/r179mult(w6,r,w2); // w6 = r/s2 (w4 in HECHECC)180sqr(w5,w6); // w5 = (r/s2)^2181multx(d0,w2); // d0 = s0'/s2 = s0182multx(d1,w2); // d1 = s1'/s2 = s1183/// dbg_printf ("s = x^2 + %lux + %lu\n", d1, d0);184185// 5. Compute z = su1186mult (w0,d0,u1[0]); // w0 = z0 = s0u10187mult (w1,d1,u1[0]);188mult (t0,d0,u1[1]);189addt(w1,t0); // w1 = z1 = s1u10+s0u11190mult (w2,d0,u1[2]);191mult(t0,d1,u1[1]);192addt(w2,t0);193addt(w2,u1[0]); // w2 = z2 = s0u12+s1u11+u10194mult(w3,d1,u1[2]);195addt(w3,d0);196addt(w3,u1[1]); // w3 = z3 = s1u12+s0+u11197add(w4,d1,u1[2]); // w4 = z4 = u1[2],s1198/// dbg_printf ("z = x^5 + %lux^4 + %lux^3 + %lux^2 + %lux + %lu\n", w4, w3, w2, w1, w0);199200// 6. Compute u' = [s(z+2w6v1) - w5((u20-v1^2)]/u2 note h = 0, w6 is w4 in handbook201add(r,w4,d1);202subf(r,u2[2]); // r = u'3 = z4+s1-u22203mult(x2,d1,w4);204mult(t0,r,u2[2]);205subf(x2,t0);206subf(x2,u2[1]);207addt(x2,w3);208addt(x2,d0); // x2 = u'2 = -u22u'3 - u21 + z3 + s0 + s1z4209mult(x1,w6,v1[2]);210dbl(x1);211mult(t0,d1,w3);212addt(x1,t0);213mult(t0,d0,w4);214addt(x1,t0);215addt(x1,w2);216subf(x1,w5);217mult(t0,x2,u2[2]);218subf(x1,t0);219mult(t0,r,u2[1]);220subf(x1,t0);221subf(x1,u2[0]); // x1 = u'1 = 2w6v12 + s1z3 + s0z4 + z2 - w5 - u22u'2 - u21u'3 - u2[0]222mult(x0,d1,v1[2]);223addt(x0,v1[1]);224multx(x0,w6);225dbl(x0);226mult(t0,d1,w2);227addt(x0,t0);228addt(x0,w1);229mult(t0,d0,w3);230addt(x0,t0);231mult(t0,w5,u1[2]);232addt(x0,t0);233mult(t0,u2[2],x1);234subf(x0,t0);235mult(t0,u2[1],x2);236subf(x0,t0);237mult(t0,u2[0],r);238subf(x0,t0); // x0 = u'0 = 2w6(v11+s1v12) + s1z2 + z1 + s0z3 + w5u12 - u22u'1 - u21u'2 - u20u'3239/// dbg_printf ("u' = x^4 + %lux^3 + %lux^2 + %lux + %lu\n", r, x2, x1, x0);240241// 7. Compute v' = w7z - v1 mod u' note h = 0 and w7 is -w3 in handbook242sub(w5,r,w4); // w5 = t1 = u'3 - z4243mult(d0,x0,w5);244addt(d0,w0);245multx(d0,w7);246subf(d0,v1[0]); // d0 = v'0 = w7(u'0t1+z0) - v10247mult(d1,x1,w5);248subf(d1,x0);249addt(d1,w1);250multx(d1,w7);251subf(d1,v1[1]); // d1 =-v'1 = w7(u'1t1-u'0+z1) - v11252mult(d2,x2,w5);253subf(d2,x1);254addt(d2,w2);255multx(d2,w7);256subf(d2,v1[2]); // d2 = v'2 = w7(u'2t1-u'1+z2) - v12257mult(w0,r,w5);258subf(w0,x2);259addt(w0,w3);260multx(w0,w7); // w0 = v'3 = w7(u'3t1 - u'2 + z3)261/// dbg_printf ("v' = %lux^3 + %lux^2 + %lux + %lu\n", w0, d2, d1, d0);262263// 8. reduce u' to u'' = (f-v'^2)/u'264_ff_set_one(u[3]);265sqr(t0,w0);266addt(t0,r);267neg(u[2],t0); // u[2] = u''2 = -(u'3+v'3^2) note f6 = 0268mult(t0,r,u[2]); // t0 = u'3u''2269addt(t0,x2); // t0 = u'3u''2+u'2270mult(w7,d2,w0);271dbl(w7); // w7 = 2v'2v'3272addt(t0,w7);273neg(u[1],t0);274#if ! HECURVE_SPARSE275addt(u[1],f[5]); // u[1] = u''1 = -(u'2 + u''2u'3 + 2v'2v'3) + f5276#endif277mult(t0,u[2],x2); // t0 = u''2u'2278addt(t0,x1); // t0 = u''2u'2+u'1279mult(w7,u[1],r); // w7 = u''1u'3280addt(t0,w7);281mult(w7,d1,w0);282dbl(w7); // w7 = 2v'1v'3283addt(t0,w7)284sqr(w7,d2); // w7 = v'2^2285addt(t0,w7);286neg(u[0],t0);287#if ! HECURVE_SPARSE288addt(u[0],f[4]); // u[0] = u''0 = -(u'1 + u''2u'2 + u''1u'3 + 2v'1v'3 + v'2^2) + f4289#endif290/// dbg_printf ("u = x^3 + %lux^2 + %lux + %lu\n", u[2], u[1], u[0]);291292// 9. compute v'' = -v' mod u3 note h = 0293mult(t0,w0,u[2]);294sub(v[2],t0,d2); // v''2 = v'3u''2 - v'2295mult(t0,w0,u[1]);296sub(v[1],t0,d1); // v'1 = v'3u''1 - v'1297mult(t0,w0,u[0]);298sub(v[0],t0,d0); // v''0 = v'3u''0 - v'0299/// dbg_printf ("v = %lux^2 + %lux + %lu\n", v[2], v[1], v[0]);300301#if HECURVE_VERIFY302if ( ! hecurve_verify (u, v, f) ) {303err_printf ("hecurve_compose_genus3 output verification failed for inputs:\n");304err_printf (" "); hecurve_print(u1,v1);305err_printf (" "); hecurve_print(u2,v2);306err_printf ("note that inputs may have been modified if output overlapped.\n");307exit (0);308}309#endif310311return 1;312}313314315int hecurve_g3_square (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS],316ff_t u1[HECURVE_GENUS+1], ff_t v1[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1], hecurve_ctx_t *ctx)317{318_ff_t_declare_reg t0, w0, w1, w2, w3, w4, w5, w6, w7, r, z0, z1, z2, g0, g1, g2, g3,g4;319320if ( ctx && ctx->state == 1 ) {321// get invert result and restore saved variables322_ff_set (w1, ctx->invert); // inverted value of r*s1323_ff_set (r, ctx->r);324_ff_set (z0, ctx->s0);325_ff_set (z1, ctx->s1);326_ff_set (z2, ctx->s2);327/// dbg_printf ("Restored r = %lu, s2 = %lu, s1 = %lu, s0 = %lu, w1 = %lu\n", r, z2, z1, z0, w1);328goto hecurve_g3_square_inverted;329}330331#if ! HECURVE_FAST332if ( dbg_level >= 2 ) {333printf ("hecurve_g3_square input\n"); hecurve_print(u1,v1);334}335#endif336#if HECURVE_VERIFY337if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_g3_square: invalid input\n"); exit (0); }338#endif339340if ( ! _ff_one(u1[3]) ) { hecurve_compose_cantor(u,v,u1,v1,u1,v1,f); return 1; }341342// 1. Compute r = Resultant(u,2v)343add(z0,v1[0],v1[0]); // z0 = h'0 = 2v0344add(z1,v1[1],v1[1]); // z1 = h'1 = 2v1345add(z2,v1[2],v1[2]); // z2 = h'2 = 2v2346mult(t0,u1[1],z2);347mult(w1,u1[2],z1);348subf(w1,t0); // w1 = t1-t2 = u2z1-u1z2349mult(t0,u1[0],z1);350mult(w2,u1[1],z0);351subf(w2,t0); // w2 = t3-t4 = u1z0-u0z1352mult(t0,u1[0],z2);353mult(w3,u1[2],z0);354subf(w3,t0); // w3 = t5-t6 = u2z0-u0z2355mult(t0,z2,w2);356sqr(w4,z0);357subf(w4,t0); // w4 = t7-t9 = z0^2 = z2w2358mult(w6,z1,z0); // w6 = t11 = z1z0359mult(w5,z2,w3);360subf(w5,w6); // w5 = t10-t11 = z2w3 - z1z0361sqr(w0,z1); // w0 = t8 = z1^2362add(r,z0,w1);363multx(r,w4);364sub(t0,w5,w6);365multx(t0,w3);366addt(r,t0);367mult(t0,w0,w2);368addt(r,t0); // r = (z0+w1)w4 + w3(w5+z1z0) + w0w2369/// dbg_printf ("r = %lu\n", r);370371// 2. Compute inv = r/2v mod u372add(t0,w1,z0);373multx(t0,z2);374sub(w2,w0,t0); // w2 = inv2 = w0-z2(w1+z0)375mult(w1,w2,u1[2]);376addt(w1,w5); // w1 = inv1 = inv2u2 + w5377mult(w0,w2,u1[1]);378mult(t0,w5,u1[2]);379addt(w0,t0);380addt(w0,w4); // w0 = inv0 = inv2u1+u2w5+w4381/// dbg_printf ("inv = %lux^2 + %lux + %lu\n", w2, w1, w0);382383// 3. Compute z = (f-v^2)/u mod u384mult(w5,u1[1],u1[2]); // w5 = -t13 = u1u2 note that f6 = 0 so z'3 = -u2385sqr(w4,u1[2]);386subf(w4,u1[1]);387#if ! HECURVE_SPARSE388addt(w4,f[5]); // w4 = z'2 = u2^2-u1+f5 note h and f6 = 0389#endif390sqr(w3,v1[2]);391subf(w3,w5);392mult(t0,w4,u1[2]);393addt(w3,t0);394addt(w3,u1[0]);395ff_negate(w3);396#if ! HECURVE_SPARSE397addt(w3,f[4]); // w3 = z'1 = -(v2^2+w5+w4u2+u0) + f4398#endif399/// dbg_printf ("z' = x^4 - %lux^3 + %lux^2 + %lux + ?, w5 = -t13 = u1u2 = %lu\n", u1[2], w4, w3, w5);400add(z2,u1[2],u1[2]);401addt(z2,u1[2]);402multx(z2,u1[2]);403add(t0,u1[1],u1[1]);404subf(z2,t0);405#if ! HECURVE_SPARSE406addt(z2,f[5]); // z2 = 3u2^2-2u1+f5407#endif408add(z1,w5,w5);409addt(z1,w3);410subf(z1,u1[0]); // z1 = 2u1u2+w3-u0411mult(t0,v1[1],v1[2]);412dbl(t0);413mult(z0,w4,u1[1]);414addt(t0,z0);415mult(z0,w3,u1[2]);416addt(t0,z0);417add(z0,u1[2],u1[2]);418addt(z0,u1[2]);419multx(z0,u1[0]);420subf(z0,t0);421#if ! HECURVE_SPARSE422addt(z0,f[3]); // z0 = 3u0u2 - (2v1v2+z'2u1+z'1u2) + f3423#endif424/// dbg_printf ("z = %lux^2 + %lux + %lu\n", z2, z1, z0);425426// 4. Compute s' = (z inv) mod u427mult(t0,w1,z0);428mult(w3,w0,z1);429addt(w3,t0); // w3 = r'1 = w0z1+w1z0430mult(w4,w1,z1);431mult(t0,w0,z2);432addt(w4,t0);433mult(t0,w2,z0);434addt(w4,t0); // w4 = r'2 = w1z1+w0z2+w2z0435mult(t0,w2,z1);436mult(w5,w1,z2);437addt(w5,t0); // w5 = r'3 = w1z2+w2z1438multx(z2,w2); // z2 = r'4439mult(w6,z2,u1[2]);440subf(w6,w5); // w6 = t18 = u2z2-w5441mult(w1,w6,u1[0]); // w1 = t15442mult(w2,z2,u1[1]); // w2 = t16443multx(z0,w0);444addt(z0,w1); // z0 = s'0 = z0w0+w1445sub(t0,w6,z2);446add(z1,u1[0],u1[1]);447multx(z1,t0);448addt(z1,w3);449addt(z1,w2);450subf(z1,w1); // z1 = s'1 = w3+(u1+u0)(w6-z2)+w2-w1451mult(z2,w6,u1[2]);452addt(z2,w4);453subf(z2,w2); // z2 = s'2 = w4-w2+u2w6454/// dbg_printf ("s' = %lux^2 + %lux + %lu\n", z2, z1, z0);455456mult(t0,r,z2);457if ( _ff_zero(t0) ) { hecurve_compose_cantor(u,v,u1,v1,u1,v1,f); return 1; }458if ( ctx && ! ctx->state ) {459_ff_set (ctx->s0, z0);460_ff_set (ctx->s1, z1);461_ff_set (ctx->s2, z2);462_ff_set (ctx->r, r);463_ff_set (ctx->invert, t0); // return to let caller invert464ctx->state = 1;465/// dbg_printf("Returning to let caller invert %lu\n", t0);466return 0;467}468_ff_invert(w1,t0);469470hecurve_g3_square_inverted: // caller returns here after inverting471// we assume w1, r, z0, z1, and z2 are set, all others free472// 5. Compute s = s'/r and make s monic473mult(w2,w1,r); // w2 = w1r474sqr(w3,z2);475multx(w3,w1);476ff_negate(w3); // w3 = -w1s'2^2 (note sign change)477mult(w4,w2,r); // w4 = r/s'2478sqr(w5,w4);479multx(z0,w2); // z0 = s0 = w2s'0480multx(z1,w2); // z1 = s1 = w2s'1481/// dbg_printf ("s = x^2 + %lux + %lu, w3 = %lu (-), w4 = %lu, w5 = %lu\n", z1, z0, w3, w4, w5);482483// 6. Compute G=su484mult(g0,z0,u1[0]); // g0 = z0u1485mult(t0,z1,u1[0]);486mult(g1,z0,u1[1]);487addt(g1,t0); // g1 = z1u0+z0u1488mult(g2,z0,u1[2]);489mult(t0,z1,u1[1]);490addt(g2,t0);491addt(g2,u1[0]); // g2 = z0u2+z1u1+u0492mult(g3,z1,u1[2]);493addt(g3,z0);494addt(g3,u1[1]); // g3 = z1u2+z0+u1495add(g4,z1,u1[2]); // g4 = z1+u2496/// dbg_printf ("G = su = x^5 + %lux^4 + %lux^3 + %lux^2 + %lux + %lu\n", g4, g3, g2, g1, g0);497498// 7. Compute u' = [(G+w4v)^2 + w5f]/u^2499add(w6,z1,z1); // w6 = u'3 = 2z1500sqr(w2,z1);501add(t0,z0,z0);502addt(w2,t0); // w2 = u'2 = z1^2+2z0503mult(t0,w4,v1[2]);504mult(w1,z0,z1);505addt(w1,t0);506dbl(w1);507subf(w1,w5); // w1 = u'1 = 2(z0z1+w4v2)-w5508sub(t0,z1,u1[2]);509multx(t0,v1[2]);510addt(t0,v1[1]);511multx(t0,w4);512multx(w5,u1[2]);513addt(t0,w5);514dbl(t0);515sqr(w0,z0);516addt(w0,t0); // w0 = u'0 = z0^2 + 2(w4(v1+v2(z1-u2))+w5u2)517/// dbg_printf ("u' = x^4 + %lux^3 + %lux^2 + %lux + %lu\n", w6, w2, w1, w0);518519// 8. Compute v' = -(Gw3 +v) mod u'520sub(w4,w6,g4); // w4 = t1 = w6-g4521subf(g3,w2);522mult(t0,w4,w6);523addt(g3,t0);524multx(g3,w3); // g3 = v'3 = w3(g3-w2+w4w6) (note w3 sign changed from HECHECC)525subf(g2,w1);526mult(t0,w4,w2);527addt(g2,t0);528multx(g2,w3);529subf(g2,v1[2]); // g2 = v'2 = w3(g2-w1+w4w2) - v2530subf(g1,w0);531mult(t0,w4,w1);532addt(g1,t0);533multx(g1,w3);534subf(g1,v1[1]); // g1 = v'1 = w3(g1-w0+w4w1) - v1535mult(t0,w4,w0);536addt(g0,t0);537multx(g0,w3);538subf(g0,v1[0]); // g0 = v'0 = w3(g0+w4w0) - v0539/// dbg_printf ("v' = %lux^3 + %lux^2 + %lux + %lu\n", g3, g2, g1, g0);540541// 9. Compute u'' = (f-v'^2)/u'542_ff_set_one(u[3]);543sqr(t0,g3);544addt(t0,w6);545neg(u[2],t0); // u[2] = u''2 = -(w6+g3^2)546mult(t0,g2,g3);547dbl(t0);548mult(z0,w6,u[2]);549addt(z0,t0);550addt(z0,w2);551neg(u[1],z0);552#if ! HECURVE_SPARSE553addt(u[1],f[5]); // u[1] = u''1 = -(w2+w6u[2]+2g1g2) + f5554#endif555sqr(t0,g2);556mult(z0,g1,g3);557dbl(z0);558addt(z0,t0);559mult(t0,w6,u[1]);560addt(z0,t0);561mult(t0,w2,u[2]);562addt(z0,t0);563addt(z0,w1);564neg(u[0],z0);565#if ! HECURVE_SPARSE566addt(u[0],f[4]); // u[0] = u''0 = -(w1+w2u[2]+w6u[1] + 2g1g3+g2^2) + f4567#endif568/// dbg_printf ("u = x^3 + %lux^2 + %lux + %lu\n", u[2], u[1], u[0]);569570// 10. Compute v'' = -v' mod u''571mult(t0,g3,u[2]);572sub(v[2],t0,g2); // v[2] = v''2 = g2+g3u[2]573mult(t0,g3,u[1]);574sub(v[1],t0,g1); // v[1] = v''1 = g1+g3u[1]575mult(t0,g3,u[0]);576sub(v[0],t0,g0); // v[0] = v'0 = g0+g3u[0]577/// dbg_printf ("v = %lux^2 + %lux + %lu\n", v[2], v[1], v[0]);578579580#if HECURVE_VERIFY581if ( ! hecurve_verify (u, v, f) ) {582err_printf ("hecurve_g3_square output verification failed for input:\n");583err_printf (" "); hecurve_print(u1,v1);584err_printf ("note that input may have been modified if output overlapped.\n");585exit (0);586}587#endif588589return 1;590}591592#endif593594595