aboutsummaryrefslogtreecommitdiff
path: root/test/sca/test_leakage_models.py
blob: b40da326cf26d6f8f1e330fe8478a4b1802b982b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import pytest

from pyecsca.ec.context import local, DefaultContext
from pyecsca.ec.formula import FormulaAction, OpResult
from pyecsca.ec.mod import mod
from pyecsca.ec.mult import LTRMultiplier
from pyecsca.ec.op import OpType
from pyecsca.sca.attack.leakage_model import Identity, Bit, Slice, HammingWeight, HammingDistance, BitLength


def test_identity():
    val = mod(3, 7)
    lm = Identity()
    assert lm(val) == 3


def test_bit():
    val = mod(3, 7)
    lm = Bit(0)
    assert lm(val) == 1
    lm = Bit(4)
    assert lm(val) == 0
    with pytest.raises(ValueError):
        Bit(-3)


def test_slice():
    val = mod(0b11110000, 0xf00)
    lm = Slice(0, 4)
    assert lm(val) == 0
    lm = Slice(1, 5)
    assert lm(val) == 0b1000
    lm = Slice(4, 8)
    assert lm(val) == 0b1111
    with pytest.raises(ValueError):
        Slice(7, 1)


def test_hamming_weight():
    val = mod(0b11110000, 0xf00)
    lm = HammingWeight()
    assert lm(val) == 4


def test_hamming_distance():
    a = mod(0b11110000, 0xf00)
    b = mod(0b00010000, 0xf00)
    lm = HammingDistance()
    assert lm(a, b) == 3


def test_bit_length():
    a = mod(0b11110000, 0xf00)
    lm = BitLength()
    assert lm(a) == 8


@pytest.fixture()
def context(secp128r1):
    scalar = 0x123456789
    mult = LTRMultiplier(
        secp128r1.curve.coordinate_model.formulas["add-1998-cmo"],
        secp128r1.curve.coordinate_model.formulas["dbl-1998-cmo"],
        secp128r1.curve.coordinate_model.formulas["z"],
        always=True,
        complete=False,
        short_circuit=True,
    )
    with local(DefaultContext()) as ctx:
        mult.init(secp128r1, secp128r1.generator)
        mult.multiply(scalar)
    return ctx


def test_mult_hw(context):
    lm = HammingWeight()
    trace = []

    def callback(action):
        if isinstance(action, FormulaAction):
            for intermediate in action.op_results:
                leak = lm(intermediate.value)
                trace.append(leak)

    context.actions[0].walk(callback)
    assert len(trace) > 0


def test_mult_hd(context):
    lm = HammingDistance()
    trace = []

    def callback(action):
        if isinstance(action, FormulaAction):
            for intermediate in action.op_results:
                if intermediate.op == OpType.Mult:
                    values = list(map(lambda v: v.value if isinstance(v, OpResult) else v, intermediate.parents))
                    leak = lm(*values)
                    trace.append(leak)

    context.actions[0].walk(callback)
    assert len(trace) > 0