Simulation using rainbow simulator

Initialisation

[ ]:
from pyecsca.ec.mult import LTRMultiplier
from pyecsca.ec.mod import Mod
from pyecsca.ec.point import Point, InfinityPoint
from pyecsca.ec.model import ShortWeierstrassModel
from pyecsca.ec.curve import EllipticCurve
from pyecsca.ec.params import DomainParameters
from pyecsca.ec.configuration import *

from pyecsca.codegen.common import Platform
from pyecsca.codegen.common import DeviceConfiguration
from pyecsca.codegen.builder import render
from pyecsca.codegen.client import SimulatorTarget

from rainbow import Print, TraceConfig, HammingWeight
from binascii import hexlify
from random import randbytes
from subprocess import run
from os.path import join

Generate source code

We will first create a DeviceConfiguration, which we will then generate and build.

[ ]:
platform = Platform.STM32F3
hash_type = HashType.SHA1
mod_rand = RandomMod.REDUCE
mult = Multiplication.BASE
sqr = Squaring.BASE
red = Reduction.BASE
inv = Inversion.GCD

model = ShortWeierstrassModel()
coords = model.coordinates["projective"]
add = coords.formulas["add-1998-cmo"]
dbl = coords.formulas["dbl-1998-cmo"]
scl = coords.formulas["z"]
formulas = [add, dbl, scl]
scalarmult = LTRMultiplier(add, dbl, scl)

config = DeviceConfiguration(model, coords, formulas, scalarmult,
                                                     hash_type, mod_rand, mult, sqr, red,
                                                     inv, platform, True, True, True)

config

Now we can render the configuration, which will generate the source files into a randomly created temporary directory, and return the path to the directory as well as names of the elf and hex files which will be built in that directory.

[ ]:
directory, elf_name, hex_name = render(config)

print(directory)

When we have the implementation rendered, we can build it using make.

[ ]:
run(["make"], cwd=directory)

Setup simulator

Setup parameters for simulator use

[ ]:
model = ShortWeierstrassModel()
coords = model.coordinates["projective"]
p = 0xd7d1247f
a = Mod(0xa4a44016, p)
b = Mod(0x73f76716, p)
n = 0xd7d2a475
h = 1
gx, gy, gz = Mod(0x54eed6d7, p), Mod(0x6f1e55ac, p), Mod(1, p)
generator = Point(coords, X=gx, Y=gy, Z=gz)
neutral = InfinityPoint(coords)

curve = EllipticCurve(model, coords, p, neutral, {"a": a, "b": b})
params = DomainParameters(curve, generator, n, h)

//TODO: describe traceconfig, printconfig, breakpoints

[ ]:
target = SimulatorTarget(model, coords, trace_config=TraceConfig(mem_value=HammingWeight()))

Connect the simulator to our generated source code

[ ]:
target.connect(binary=join(directory, elf_name))

Using the simulator

Set up curve parameters. It is needed for next operations.

[ ]:
target.set_params(params)

Perform scalar multiplication on given point with given scalar

[ ]:
point = target.scalar_mult(0xFFFFAAAA, params.generator)
print(point)

#Compare with pyecsca
generator = params.generator
model = params.curve.model
coords = params.curve.coordinate_model
add = coords.formulas["add-2007-bl"]
dbl = coords.formulas["dbl-2007-bl"]
mult = LTRMultiplier(add, dbl, None)
mult.init(params, generator)
resPoint = mult.multiply(0xFFFFAAAA)
print(point.equals(resPoint))

Generate private and public key

[ ]:
seed_bytes = randbytes(32)
target.init_prng(seed_bytes)
priv, pub = target.generate()

print("private key:", priv)
print("public key:", pub)
# Check if it is valid keypair.
print(params.curve.is_on_curve(pub))
print(params.curve.affine_multiply(params.generator.to_affine(), priv))

Set private and public key.

[ ]:
print("Before private:", target.privkey)
print("Before public:", target.pubkey)

target.set_privkey(priv)
target.set_pubkey(pub)

print("After private:", target.privkey)
print("After public:", target.pubkey)

Perform key agreement using ecdh

[ ]:
other_priv, other_pub = target.generate()
shared_secret = target.ecdh(other_pub)
print("shared secret:", hexlify(shared_secret))

Perform signing over given data and verify the signature

[ ]:
message = "test message"
signed_message = target.ecdsa_sign(message.encode())
res = target.ecdsa_verify(message.encode(), bytes(signed_message))
print(res)
[ ]:
message = "test message 2"
signed_message = target.ecdsa_sign(message.encode())
message = "test message 3"
res = target.ecdsa_verify(message.encode(), bytes(signed_message))
print(res)

Get a trace of the simulation

[ ]:
print(target.trace[0:10])

Deinitialisation

[ ]:
target.disconnect()