# This file is part of lascar
#
# lascar is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#
# Copyright 2018 Manuel San Pedro, Victor Servant, Charles Guillemet, Ledger SAS - manuel.sanpedro@ledger.fr, victor.servant@ledger.fr, charles@ledger.fr
"""
Classes for leakage models
"""
import numpy as np
try:
from numba import jit
except Exception:
print("Numba not present. Jitter will be off.")
def jit(*args, **kwargs):
return lambda x: x
_hw = np.array(
[
0,
1,
1,
2,
1,
2,
2,
3,
1,
2,
2,
3,
2,
3,
3,
4,
1,
2,
2,
3,
2,
3,
3,
4,
2,
3,
3,
4,
3,
4,
4,
5,
1,
2,
2,
3,
2,
3,
3,
4,
2,
3,
3,
4,
3,
4,
4,
5,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
1,
2,
2,
3,
2,
3,
3,
4,
2,
3,
3,
4,
3,
4,
4,
5,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
3,
4,
4,
5,
4,
5,
5,
6,
4,
5,
5,
6,
5,
6,
6,
7,
1,
2,
2,
3,
2,
3,
3,
4,
2,
3,
3,
4,
3,
4,
4,
5,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
3,
4,
4,
5,
4,
5,
5,
6,
4,
5,
5,
6,
5,
6,
6,
7,
2,
3,
3,
4,
3,
4,
4,
5,
3,
4,
4,
5,
4,
5,
5,
6,
3,
4,
4,
5,
4,
5,
5,
6,
4,
5,
5,
6,
5,
6,
6,
7,
3,
4,
4,
5,
4,
5,
5,
6,
4,
5,
5,
6,
5,
6,
6,
7,
4,
5,
5,
6,
5,
6,
6,
7,
5,
6,
6,
7,
6,
7,
7,
8,
],
dtype=np.uint8,
)
[docs]@jit(nopython=True)
def hamming(value):
r = np.uint32(0)
while value:
r += _hw[value & 0xFF]
value >>= 8
return r
[docs]@jit(nopython=True)
def hamming_weight(value):
"""
Compute the hamming weight of an integer
https://www.expobrain.net/2013/07/29/hamming-weights-python-implementation/
:param value: the integer
:return: the hamming weight of the value
"""
value = int(value)
value -= (value >> 1) & 0x5555555555555555
value = (value & 0x3333333333333333) + ((value >> 2) & 0x3333333333333333)
value = (value + (value >> 4)) & 0x0F0F0F0F0F0F0F0F
return ((value * 0x0101010101010101) & 0xFFFFFFFFFFFFFFFF) >> 56
[docs]class LeakageModel:
"""
LeakageModel is an abstract class.
A leakage model is a callable object. It can be defined by a simple function,
or by a class (like LeakageModel) overloading :meth:`__call__`
"""
def __call__(self, value):
pass
[docs]class HammingPrecomputedModel(LeakageModel):
"""
Emulates the hamming weight leakage model by precomputing all the hamming weigths
until a given values.
"""
def __init__(self, max=256):
"""
HammingWeightEightBitsModel constructor: precompute _table with the 256 values
:param max: maximum value to precompute
"""
self._table = np.zeros((max,), np.uint8)
for i in range(max):
self._table[i] = hamming_weight(i)
def __call__(self, value):
return self._table[value]
[docs]class BitLeakageModel(LeakageModel):
"""
BitLeakageModel returns the value of a specified bit.
"""
def __init__(self, bit):
self._bit = bit
def __call__(self, value):
return (value >> self._bit) & 1