diff options
Diffstat (limited to 'pyecsca/codegen')
| -rw-r--r-- | pyecsca/codegen/builder.py | 225 | ||||
| -rw-r--r-- | pyecsca/codegen/client.py | 85 | ||||
| -rw-r--r-- | pyecsca/codegen/common.py | 145 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/main.c | 14 | ||||
| -rw-r--r-- | pyecsca/codegen/templates/mult_ldr.c | 6 |
5 files changed, 296 insertions, 179 deletions
diff --git a/pyecsca/codegen/builder.py b/pyecsca/codegen/builder.py index 3970d21..d65eb2b 100644 --- a/pyecsca/codegen/builder.py +++ b/pyecsca/codegen/builder.py @@ -4,12 +4,10 @@ import re import shutil import subprocess import tempfile -from ast import operator, Add, Sub, Mult, Div, Pow +from ast import Pow from copy import copy -from dataclasses import dataclass -from enum import Enum from os import path -from typing import List, Set, Mapping, Any, Optional, Type, Tuple, MutableMapping +from typing import List, Set, Mapping, Any, Optional, Tuple, MutableMapping import click from jinja2 import Environment, PackageLoader @@ -23,152 +21,41 @@ from pyecsca.ec.model import (CurveModel, ShortWeierstrassModel, MontgomeryModel TwistedEdwardsModel) from pyecsca.ec.mult import (ScalarMultiplier, LTRMultiplier, RTLMultiplier, CoronMultiplier, LadderMultiplier, SimpleLadderMultiplier, DifferentialLadderMultiplier, - WindowNAFMultiplier, BinaryNAFMultiplier) -from pyecsca.ec.op import CodeOp + BinaryNAFMultiplier) +from pyecsca.ec.op import CodeOp, OpType + +from .common import (Platform, Multiplication, Squaring, Reduction, HashType, RandomMod, + Configuration, MULTIPLIERS, wrap_enum) env = Environment( loader=PackageLoader("pyecsca.codegen") ) -def render_op(op: operator, result: str, left: str, right: str, mod: str) -> Optional[str]: - if isinstance(op, Add): +def render_op(op: OpType, result: str, left: str, right: str, mod: str) -> Optional[str]: + if op == OpType.Add: return "bn_mod_add(&{}, &{}, &{}, &{});".format(left, right, mod, result) - elif isinstance(op, Sub): + elif op == OpType.Sub: return "bn_mod_sub(&{}, &{}, &{}, &{});".format(left, right, mod, result) - elif isinstance(op, Mult): + elif op == OpType.Mult: return "bn_mod_mul(&{}, &{}, &{}, &{});".format(left, right, mod, result) - elif isinstance(op, Div): + elif op == OpType.Div or op == OpType.Inv: return "bn_mod_div(&{}, &{}, &{}, &{});".format(left, right, mod, result) - elif isinstance(op, Pow) and right == 2: + elif op == OpType.Sqr: return "bn_mod_sqr(&{}, &{}, &{});".format(left, mod, result) - elif isinstance(op, Pow): + elif op == OpType.Pow: return "bn_mod_pow(&{}, &{}, &{}, &{});".format(left, right, mod, result) - elif op is None: + elif op == OpType.Id: return "bn_copy(&{}, &{});".format(left, result) else: print(op, result, left, right, mod) + return None env.globals["render_op"] = render_op env.globals["isinstance"] = isinstance -class EnumDefine(Enum): - def __str__(self): - return self.value - - def __repr__(self): - return self.value - - @classmethod - def names(cls): - return list(e.name for e in cls) - - -@public -class Platform(EnumDefine): - """Platform to build for.""" - HOST = "HOST" - XMEGA = "CW308_XMEGA" - STM32F0 = "CW308_STM32F0" - STM32F3 = "CW308_STM32F3" - - -@public -class Multiplication(EnumDefine): - """Base multiplication algorithm to use.""" - TOOM_COOK = "MUL_TOOM_COOK" - KARATSUBA = "MUL_KARATSUBA" - COMBA = "MUL_COMBA" - BASE = "MUL_BASE" - - -@public -class Squaring(EnumDefine): - """Base squaring algorithm to use.""" - TOOM_COOK = "SQR_TOOM_COOK" - KARATSUBA = "SQR_KARATSUBA" - COMBA = "SQR_COMBA" - BASE = "SQR_BASE" - - -@public -class Reduction(EnumDefine): - """Modular reduction method used.""" - BARRETT = "RED_BARRETT" - MONTGOMERY = "RED_MONTGOMERY" - BASE = "RED_BASE" - - -@public -class HashType(EnumDefine): - """Hash algorithm used in ECDH and ECDSA.""" - NONE = "HASH_NONE" - SHA1 = "HASH_SHA1" - SHA224 = "HASH_SHA224" - SHA256 = "HASH_SHA256" - SHA384 = "HASH_SHA384" - SHA512 = "HASH_SHA512" - - -@public -class RandomMod(EnumDefine): - """Method of sampling a uniform integer modulo order.""" - SAMPLE = "MOD_RAND_SAMPLE" - REDUCE = "MOD_RAND_REDUCE" - - -@public -@dataclass -class Configuration(object): - platform: Platform - hash_type: HashType - mod_rand: RandomMod - mult: Multiplication # TODO: Use this - sqr: Squaring # TODO: Use this - red: Reduction # TODO: Use this - model: CurveModel - coords: CoordinateModel - formulas: List[Formula] - scalarmult: ScalarMultiplier - -MULTIPLIERS = [ - { - "name": ("rtl", "RTLMultiplier"), - "class": LTRMultiplier - }, - { - "name": ("rtl", "RTLMultiplier"), - "class": RTLMultiplier - }, - { - "name": ("coron", "CoronMultiplier"), - "class": CoronMultiplier - }, - { - "name":("ldr", "LadderMultiplier"), - "class": LadderMultiplier - }, - { - "name": ("simple-ldr", "SimpleLadderMultiplier"), - "class": SimpleLadderMultiplier - }, - { - "name": ("diff-ldr", "DifferentialLadderMultiplier"), - "class": DifferentialLadderMultiplier - }, - { - "name": ("naf", "bnaf", "BinaryNAFMultiplier"), - "class": BinaryNAFMultiplier - }, - { - "name": ("wnaf", "WindowNAFMultiplier"), - "class": WindowNAFMultiplier - } -] - - def render_defs(model: CurveModel, coords: CoordinateModel) -> str: return env.get_template("defs.h").render(params=model.parameter_names, variables=coords.variables) @@ -185,7 +72,7 @@ def transform_ops(ops: List[CodeOp], parameters: List[str], outputs: Set[str], return renames.get(name, name) return name - allocations = [] + allocations: List[str] = [] initializations = {} const_mapping = {} operations = [] @@ -302,9 +189,10 @@ def render_scalarmult_impl(scalarmult: ScalarMultiplier) -> str: BinaryNAFMultiplier=BinaryNAFMultiplier) -def render_main(model: CurveModel, coords: CoordinateModel) -> str: +def render_main(model: CurveModel, coords: CoordinateModel, keygen: bool, ecdh: bool, ecdsa: bool) -> str: return env.get_template("main.c").render(curve_variables=coords.variables, - curve_parameters=model.parameter_names) + curve_parameters=model.parameter_names, + keygen=keygen, ecdh=ecdh, ecdsa=ecdsa) def render_makefile(platform: Platform, hash_type: HashType, mod_rand: RandomMod) -> str: @@ -328,7 +216,7 @@ def render(config: Configuration) -> Tuple[str, str, str]: os.mkdir(gen_dir) save_render(temp, "Makefile", render_makefile(config.platform, config.hash_type, config.mod_rand)) - save_render(temp, "main.c", render_main(config.model, config.coords)) + save_render(temp, "main.c", render_main(config.model, config.coords, config.keygen, config.ecdh, config.ecdsa)) save_render(gen_dir, "defs.h", render_defs(config.model, config.coords)) point_render = render_coords_impl(config.coords) for formula in config.formulas: @@ -337,7 +225,8 @@ def render(config: Configuration) -> Tuple[str, str, str]: save_render(gen_dir, "point.c", point_render) save_render(gen_dir, "curve.c", render_curve_impl(config.model)) save_render(gen_dir, "mult.c", render_scalarmult_impl(config.scalarmult)) - return temp, "pyecsca-codegen-{}.elf".format(str(config.platform)), "pyecsca-codegen-{}.hex".format(str(config.platform)) + return temp, "pyecsca-codegen-{}.elf".format( + str(config.platform)), "pyecsca-codegen-{}.hex".format(str(config.platform)) @public @@ -439,23 +328,21 @@ def get_multiplier(ctx: click.Context, param, value: Optional[str]) -> Optional[ return mult -def wrap_enum(enum_class: Type[EnumDefine]): - def callback(ctx, param, value): - try: - res = getattr(enum_class, value) - return res - except Exception: - raise click.BadParameter( - "Cannot create {} enum from {}.".format(enum_class.__name__, value)) - - return callback - +def get_ecdsa(ctx: click.Context, param, value: bool) -> bool: + if not value: + return False + formulas = ctx.meta["formulas"] + if not any(isinstance(formula, AdditionFormula) for formula in formulas): + raise click.BadParameter("ECDSA needs an addition formula. None was supplied.") @click.group(context_settings={"help_option_names": ["-h", "--help"]}) @click.version_option() @public def main(): + """ + A tool for building, querying and flashing ECC implementations on devices. + """ pass @@ -484,6 +371,10 @@ def main(): type=click.Choice(Reduction.names()), callback=wrap_enum(Reduction), help="Modular reduction algorithm to use.") +@click.option("--keygen/--no-keygen", help="Whether to disable keygen.", is_flag=True, default=True) +@click.option("--ecdh/--no-ecdh", help="Whether to disable ECDH.", is_flag=True, default=True) +@click.option("--ecdsa/--no-ecdsa", help="Whether to disable ECDSA.", is_flag=True, default=True, + callback=get_ecdsa) @click.option("--strip", help="Whether to strip the binary or not.", is_flag=True) @click.option("--remove/--no-remove", help="Whether to remove the dir.", is_flag=True, default=True) @click.option("-v", "--verbose", count=True) @@ -498,8 +389,8 @@ def main(): callback=get_multiplier) @click.argument("outdir") @public -def build_impl(platform, hash, rand, mul, sqr, red, strip, remove, verbose, model, coords, formulas, scalarmult, - outdir): +def build_impl(platform, hash, rand, mul, sqr, red, keygen, ecdh, ecdsa, strip, remove, + verbose, model, coords, formulas, scalarmult, outdir): """This command builds an ECC implementation. \b @@ -510,10 +401,10 @@ def build_impl(platform, hash, rand, mul, sqr, red, strip, remove, verbose, mode OUTDIR: The output directory for files with the built impl. """ - config = Configuration(platform, hash, rand, mul, sqr, red, model, coords, formulas, scalarmult) + config = Configuration(platform, hash, rand, mul, sqr, red, model, coords, formulas, scalarmult, + keygen, ecdh, ecdsa) dir, elf_file, hex_file = render(config) - res = subprocess.run(["make"], cwd=dir, capture_output=True) if verbose >= 1: click.echo(res.stdout.decode()) @@ -540,7 +431,7 @@ def build_impl(platform, hash, rand, mul, sqr, red, strip, remove, verbose, mode callback=get_formula) @public def list_impl(model: Optional[CurveModel], coords: Optional[CoordinateModel], - formulas: Optional[Tuple[Formula]]): + formulas: Optional[Tuple[Formula]]): """This command lists possible choices for an ECC implementation. If no arguments are provided the argument lists other implementation options, such as modular reduction algorithms, build platforms and so on. @@ -575,14 +466,24 @@ def list_impl(model: Optional[CurveModel], coords: Optional[CoordinateModel], "{}: {}, [{}]".format(coord.name, coord.full_name, ",".join(coord.variables))) return if not model: - click.echo(click.wrap_text("Platform:\n\t" + ", ".join(Platform.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Hash type:\n\t" + ", ".join(HashType.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Modular Random:\n\t" + ", ".join(RandomMod.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Multiplication:\n\t" + ", ".join(Multiplication.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Squaring:\n\t" + ", ".join(Squaring.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Modular Reduction:\n\t" + ", ".join(Reduction.names()),subsequent_indent="\t")) - click.echo(click.wrap_text("Scalar multplier:\n\t" + ", ".join(map(lambda m: m["name"][-1], MULTIPLIERS)), + click.echo( + click.wrap_text("Platform:\n\t" + ", ".join(Platform.names()), + subsequent_indent="\t")) + click.echo( + click.wrap_text("Hash type:\n\t" + ", ".join(HashType.names()), + subsequent_indent="\t")) + click.echo(click.wrap_text("Modular Random:\n\t" + ", ".join(RandomMod.names()), + subsequent_indent="\t")) + click.echo(click.wrap_text("Multiplication:\n\t" + ", ".join(Multiplication.names()), + subsequent_indent="\t")) + click.echo( + click.wrap_text("Squaring:\n\t" + ", ".join(Squaring.names()), + subsequent_indent="\t")) + click.echo(click.wrap_text("Modular Reduction:\n\t" + ", ".join(Reduction.names()), subsequent_indent="\t")) + click.echo(click.wrap_text( + "Scalar multplier:\n\t" + ", ".join(map(lambda m: m["name"][-1], MULTIPLIERS)), + subsequent_indent="\t")) @main.command() @@ -592,7 +493,7 @@ def list_impl(model: Optional[CurveModel], coords: Optional[CoordinateModel], help="The platform to flash.") @click.argument("dir") @public -def flash(platform, dir): +def flash(platform, dir): # pragma: no cover """This command flashes a chip through the ChipWhisperer framework with the built implementation. \b @@ -602,14 +503,16 @@ def flash(platform, dir): import chipwhisperer as cw except ImportError: click.secho("ChipWhisperer not installed, flashing requires it.", fg="red", err=True) - return + raise click.Abort if platform in (Platform.STM32F0, Platform.STM32F3): prog = cw.programmers.STM32FProgrammer elif platform == Platform.XMEGA: prog = cw.programmers.XMEGAProgrammer else: - click.secho("Flashing the HOST is not required, just run the ELF and communicate with it via the standard IO.", fg="red", err=True) - return + click.secho( + "Flashing the HOST is not required, just run the ELF and communicate with it via the standard IO.", + fg="red", err=True) + raise click.Abort fw_path = path.join(dir, "pyecsca-codegen-{}.hex".format(platform)) scope = cw.scope() scope.default_setup() diff --git a/pyecsca/codegen/client.py b/pyecsca/codegen/client.py index dca9aee..8893a5c 100644 --- a/pyecsca/codegen/client.py +++ b/pyecsca/codegen/client.py @@ -1,16 +1,26 @@ #!/usr/bin/env python3 from binascii import hexlify -from typing import Mapping, Union, Optional +from typing import Mapping, Union, Optional, Any +from os import path import click -from pyecsca.ec.coordinates import AffineCoordinateModel -from pyecsca.ec.curve import EllipticCurve -from pyecsca.ec.group import AbelianGroup +from pyecsca.ec.params import DomainParameters from pyecsca.ec.mod import Mod -from pyecsca.ec.model import ShortWeierstrassModel -from pyecsca.ec.mult import LTRMultiplier from pyecsca.ec.point import Point +from .common import EnumDefine, wrap_enum + +try: + import chipwhisperer as cw +except ImportError: + cw = None + + +class Target(EnumDefine): + HOST = "HOST" + SIMPLESERIAL = "CWLITE_SIMPLESERIAL" + JCARD = "CWLITE_JCARD" + def encode_scalar(val: Union[int, Mod]) -> bytes: if isinstance(val, int): @@ -55,7 +65,7 @@ def cmd_init_prng(seed: bytes) -> str: return "i" + hexlify(seed).decode() -def cmd_set_curve(group: AbelianGroup) -> str: +def cmd_set_curve(group: DomainParameters) -> str: data = { "p": encode_scalar(group.curve.prime), "n": encode_scalar(group.order), @@ -96,11 +106,49 @@ def cmd_ecdsa_verify(data: bytes, sig: bytes) -> str: return "v" + hexlify(encode_data(None, {"d": data, "s": sig})).decode() -@click.command() +def setup_scope(target_type: Target): + if target_type in (Target.SIMPLESERIAL, Target.JCARD): + scope = cw.scope() + scope.default_setup() + return scope + return None + + +def connect(target_type: Target, scope, **kwargs) -> Any: + if target_type == Target.HOST: + return kwargs["binary"] + elif target_type == Target.SIMPLESERIAL: + return cw.target(scope, cw.targets.SimpleSerial) + elif target_type == Target.JCARD: + return None # TODO: this + + +def send_command(target_type: Target, target: Any, command: str) -> str: + if target_type == Target.SIMPLESERIAL: + target.write(command + "\n") + result = target.read() + target.simpleserial_wait_ack() + return result + return None # TODO: this + + +@click.group(context_settings={"help_option_names": ["-h", "--help"]}) +@click.option("--target", envvar="TARGET", required=True, + type=click.Choice(Target.names()), + callback=wrap_enum(Target), + help="The target to use.") +@click.option("--binary", help="For HOST target only. The binary to run.") @click.version_option() -def main(): - import chipwhisperer - pass +def main(target, binary): + """ + A tool for communicating with built and flashed ECC implementations. + """ + if target in (Target.SIMPLESERIAL, Target.JCARD) and cw is None: + click.secho("ChipWhisperer not installed, SIMPLESERIAL and JCARD targets require it.", fg="red", err=True) + raise click.Abort + if target == Target.HOST and (binary is None or not path.isfile(binary)): + click.secho("Binary is required if the target is the host.", fg="red", err=True) + raise click.Abort # model = ShortWeierstrassModel() # coords = model.coordinates["projective"] # p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff @@ -136,5 +184,20 @@ def main(): # print(ot == res) +@main.command("gen") +def generate(): + pass + + +@main.command("ecdh") +def ecdh(): + pass + + +@main.command("ecdsa") +def ecdsa(): + pass + + if __name__ == "__main__": main() diff --git a/pyecsca/codegen/common.py b/pyecsca/codegen/common.py new file mode 100644 index 0000000..e29fa00 --- /dev/null +++ b/pyecsca/codegen/common.py @@ -0,0 +1,145 @@ +from dataclasses import dataclass +from enum import Enum +from typing import List, Type +import click + +from public import public +from pyecsca.ec.coordinates import CoordinateModel +from pyecsca.ec.formula import Formula +from pyecsca.ec.model import CurveModel +from pyecsca.ec.mult import (ScalarMultiplier, LTRMultiplier, RTLMultiplier, CoronMultiplier, + LadderMultiplier, SimpleLadderMultiplier, DifferentialLadderMultiplier, + WindowNAFMultiplier, BinaryNAFMultiplier) + + +@public +class EnumDefine(Enum): + def __str__(self): + return self.value + + def __repr__(self): + return self.value + + @classmethod + def names(cls): + return list(e.name for e in cls) + + +@public +class Platform(EnumDefine): + """Platform to build for.""" + HOST = "HOST" + XMEGA = "CW308_XMEGA" + STM32F0 = "CW308_STM32F0" + STM32F3 = "CW308_STM32F3" + + +@public +class Multiplication(EnumDefine): + """Base multiplication algorithm to use.""" + TOOM_COOK = "MUL_TOOM_COOK" + KARATSUBA = "MUL_KARATSUBA" + COMBA = "MUL_COMBA" + BASE = "MUL_BASE" + + +@public +class Squaring(EnumDefine): + """Base squaring algorithm to use.""" + TOOM_COOK = "SQR_TOOM_COOK" + KARATSUBA = "SQR_KARATSUBA" + COMBA = "SQR_COMBA" + BASE = "SQR_BASE" + + +@public +class Reduction(EnumDefine): + """Modular reduction method used.""" + BARRETT = "RED_BARRETT" + MONTGOMERY = "RED_MONTGOMERY" + BASE = "RED_BASE" + + +@public +class HashType(EnumDefine): + """Hash algorithm used in ECDH and ECDSA.""" + NONE = "HASH_NONE" + SHA1 = "HASH_SHA1" + SHA224 = "HASH_SHA224" + SHA256 = "HASH_SHA256" + SHA384 = "HASH_SHA384" + SHA512 = "HASH_SHA512" + + +@public +class RandomMod(EnumDefine): + """Method of sampling a uniform integer modulo order.""" + SAMPLE = "MOD_RAND_SAMPLE" + REDUCE = "MOD_RAND_REDUCE" + + +@public +@dataclass +class Configuration(object): + platform: Platform + hash_type: HashType + mod_rand: RandomMod + mult: Multiplication # TODO: Use this + sqr: Squaring # TODO: Use this + red: Reduction # TODO: Use this + model: CurveModel + coords: CoordinateModel + formulas: List[Formula] + scalarmult: ScalarMultiplier + keygen: bool + ecdh: bool + ecdsa: bool + + +MULTIPLIERS = [ + { + "name": ("ltr", "LTRMultiplier"), + "class": LTRMultiplier + }, + { + "name": ("rtl", "RTLMultiplier"), + "class": RTLMultiplier + }, + { + "name": ("coron", "CoronMultiplier"), + "class": CoronMultiplier + }, + { + "name": ("ldr", "LadderMultiplier"), + "class": LadderMultiplier + }, + { + "name": ("simple-ldr", "SimpleLadderMultiplier"), + "class": SimpleLadderMultiplier + }, + { + "name": ("diff-ldr", "DifferentialLadderMultiplier"), + "class": DifferentialLadderMultiplier + }, + { + "name": ("naf", "bnaf", "BinaryNAFMultiplier"), + "class": BinaryNAFMultiplier + }, + { + "name": ("wnaf", "WindowNAFMultiplier"), + "class": WindowNAFMultiplier + } +] + + +@public +def wrap_enum(enum_class: Type[EnumDefine]): + def callback(ctx, param, value): + try: + res = getattr(enum_class, value) + return res + except Exception: + raise click.BadParameter( + "Cannot create {} enum from {}.".format(enum_class.__name__, value)) + + return callback diff --git a/pyecsca/codegen/templates/main.c b/pyecsca/codegen/templates/main.c index 1c9491b..e39af07 100644 --- a/pyecsca/codegen/templates/main.c +++ b/pyecsca/codegen/templates/main.c @@ -352,13 +352,19 @@ int main(void) { simpleserial_init(); simpleserial_addcmd('i', MAX_SS_LEN, cmd_init_prng); simpleserial_addcmd('c', MAX_SS_LEN, cmd_set_curve); - simpleserial_addcmd('g', 0, cmd_generate); + {%- if keygen %} + simpleserial_addcmd('g', 0, cmd_generate); + {%- endif %} simpleserial_addcmd('s', MAX_SS_LEN, cmd_set_privkey); simpleserial_addcmd('w', MAX_SS_LEN, cmd_set_pubkey); simpleserial_addcmd('m', MAX_SS_LEN, cmd_scalar_mult); - simpleserial_addcmd('e', MAX_SS_LEN, cmd_ecdh); - simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign); - simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify); + {%- if ecdh %} + simpleserial_addcmd('e', MAX_SS_LEN, cmd_ecdh); + {%- endif %} + {%- if ecdsa %} + simpleserial_addcmd('a', MAX_SS_LEN, cmd_ecdsa_sign); + simpleserial_addcmd('v', MAX_SS_LEN, cmd_ecdsa_verify); + {%- endif %} while(simpleserial_get()); return 0; }
\ No newline at end of file diff --git a/pyecsca/codegen/templates/mult_ldr.c b/pyecsca/codegen/templates/mult_ldr.c index cabab0b..c7c5246 100644 --- a/pyecsca/codegen/templates/mult_ldr.c +++ b/pyecsca/codegen/templates/mult_ldr.c @@ -3,7 +3,7 @@ void scalar_mult(bn_t *scalar, point_t *point, curve_t *curve, point_t *out) { {%- if scalarmult.complete %} - point_t *p0 = point_copy(&curve->neutral); + point_t *p0 = point_copy(curve->neutral); point_t *p1 = point_copy(point); int nbits = bn_bit_length(&curve->n) - 1; {%- else %} @@ -15,9 +15,9 @@ void scalar_mult(bn_t *scalar, point_t *point, curve_t *curve, point_t *out) { for (int i = nbits; i >= 0; i--) { if (bn_get_bit(scalar, i) == 0) { - point_ladd(p0, p1, curve, p0, p1); + point_ladd(p0, p1, point, curve, p0, p1); } else { - point_ladd(p1, p0, curve, p1, p0); + point_ladd(p1, p0, point, curve, p1, p0); } } |
