Exemplo n.º 1
0
    def export(container, leakages_filename, values_filename, name=None, batch_size=100):
        """
        export method is used to export an existing container into an NpyContainer.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container
        into a NpyContainer.

        :param container: container to be exported
        :param leakages_filename: name of the npy file to create corresponding to the leakages
        :param values_filename: name of the npy file to create corresponding to the values
        :param name: name for the session
        :param batch_size: batch_size for the session
        :return: 
        """

        leakage, value = container[0]
        out = NpyContainer._void_container(leakages_filename, values_filename, container.number_of_traces, leakage.shape, leakage.dtype,
                                           value.shape, value.dtype)

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(container, engine=ContainerDumpEngine(out), name=name if name else 'NpyContainer')
        session.run(batch_size)

        return out
Exemplo n.º 2
0
    def export(
        container,
        filename,
        name=None,
        leakages_dataset_name="leakages",
        values_dataset_name="values",
        batch_size=100,
    ):
        """
        export method is used to export an existing container into an Hdf5Container.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container.

        :param container: container to be exported
        :param filename: name of the Hdf5Container to vuild
        :param leakages_dataset_name:
        :param values_dataset_name:
        :param batch_size:
        :return:
        """

        leakage, value = container[0]
        out = Hdf5Container.void_container(
            filename,
            container.number_of_traces,
            leakage.shape,
            leakage.dtype,
            value.shape,
            value.dtype,
            leakages_dataset_name,
            values_dataset_name,
        )

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(
            container,
            engine=ContainerDumpEngine(out),
            name=name if name else "Hdf5Container",
        )
        session.run(batch_size)
        # Adding mean/var: to leakage_dataset_name as attributes
        try:
            out._file[leakages_dataset_name].attrs["mean"] = session[
                "mean"].finalize()
            out._file[leakages_dataset_name].attrs["var"] = session[
                "var"].finalize()
        except:
            pass

        return out
Exemplo n.º 3
0
 def get_leakage_mean_var(self):
     """
     Compute mean/var of the leakage.
     :return: mean/var of the container leakages
     """
     from lascar import Session
     session = Session(self).run()
     return session['mean'].finalize(), session['var'].finalize()
Exemplo n.º 4
0
def show_nicv(values, traces, nr_digits=4):
    """ Compute the Normalized Inter-Class Variance as in the article """
    import numpy as np

    values = np.array(values, dtype=np.uint8)
    traces = np.array(traces)

    from lascar import TraceBatchContainer, Session, NicvEngine, hamming

    # Use the Hamming weight of leaked values and add some noise
    # through the 'leakage_processing' parameter
    t = TraceBatchContainer(
        traces,
        values,
        leakage_processing=lambda x: np.array(
            [hamming(i) for i in x], dtype=np.uint
        )
        + np.random.normal(0, 0.5, len(x)),
    )

    s = Session(t)

    ## Input value leakage
    # s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:v[z], range(9)) for i in range(nr_digits)])

    ## Difference leakage
    s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:np.int8(v[z]) - np.int8(STORED_PIN[z]), range(-9,8)) for i in range(nr_digits)])

    ## below is a variant on the carry bit
    # s.add_engines([NicvEngine('c'+str(i), lambda v,z=i:v[z]>int(STORED_PIN[z]), range(16)) for i in range(nr_digits)])

    s.run()

    return np.array([s[eng]._finalize() for eng in s.engines if eng not in ['mean', 'var']])
Exemplo n.º 5
0
    def export(container,
               filename,
               name=None,
               leakages_dataset_name="leakages",
               values_dataset_name="values",
               batch_size=100):
        """
        export method is used to export an existing container into an Hdf5Container.

        It creates a session and use a ContainerDumpEngine to recopy the traces delivered by the original container.

        :param container: container to be exported
        :param filename: name of the Hdf5Container to vuild
        :param leakages_dataset_name:
        :param values_dataset_name:
        :param batch_size:
        :return:
        """

        leakage, value = container[0]
        out = Hdf5Container.void_container(filename,
                                           container.number_of_traces,
                                           leakage.shape, leakage.dtype,
                                           value.shape, value.dtype,
                                           leakages_dataset_name,
                                           values_dataset_name)

        from lascar import Session
        from lascar.engine import ContainerDumpEngine

        session = Session(container,
                          engine=ContainerDumpEngine(out),
                          name=name if name else 'Hdf5Container')
        session.run(batch_size)

        return out
Exemplo n.º 6
0
for i, t in enumerate(traces):
    # pad to longest trace (even though they might well be all the same length)
    tmp[i][: len(t)] = np.array(t, dtype=np.float32)
traces = tmp


## Phase 2 : attack with Lascar
## Launch 16 CPAs on the outputs of the sbox

from lascar.container import TraceBatchContainer
from lascar import Session, CpaEngine, ConsoleOutputMethod
from lascar.tools.aes import sbox

t = TraceBatchContainer(traces, values)

s = Session(t, output_method=ConsoleOutputMethod())
s.add_engines(
    [
        CpaEngine(f"cpa{i}", lambda v, k, z=i: sbox[v[z] ^ k], range(256))
        for i in range(16)
    ]
)
s.run()

print(s.output_method.finalize())

# Check the results :
print("Key should be : f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40")

K = list(
    map(lambda x: int(x, 16), "f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40".split())
Exemplo n.º 7
0
    values = np.array(values, dtype=np.uint8)

    lgst_dim = max(map(len, traces))

    # we're gonna split each 32bit value in 8 bit chunks
    lgst_dim *= 4

    tmp = np.zeros((len(traces), lgst_dim), dtype=np.float32)
    for i, t in enumerate(traces):
        for x in range(len(t)):
            for j in range(4):
                tmp[i][x * 4 + j] = (t[x] >> (8 * j)) & 0xFF

    return values, tmp, addresses


if __name__ == "__main__":
    _, func = generate_targetf()
    values, traces, addresses = get_traces(func, 10, 1000000)

    from lascar import TraceBatchContainer, Session

    t = TraceBatchContainer(traces, values)
    s = Session(t)
    s.run()

    from rainbow.utils.plot import viewer

    viewer(addresses, s["var"].finalize())
Exemplo n.º 8
0
from lascar.tools.aes import sbox


def selection_function(value, guess):
    return sbox[value['plaintext'][3] ^ guess] & 1


guess_range = range(256)

from lascar import DpaEngine
dpa_engine = DpaEngine('dpa', selection_function, guess_range)

# We can now create a Session, register the dpa_lsb_engine, and run it.
from lascar import Session
session = Session(container, engine=dpa_engine)
# session.add_engine( dpa_lsb_engine) # the engine can be added after the session creation

session.run(
    batch_size=100)  # the session will load traces by batches of 100 traces
"""
Now, to get the result, one solution could be to request the dpa_lsb_engine.finalize() method.
(As most of the engines, the finalize() method returns sca results)

For more option about how to manage results of sca, please follow the next step of the tutorial.

"""
results = dpa_engine.finalize()

print(results.shape)
print("Best Guess is %02X." % results.max(1).argmax())
Exemplo n.º 9
0
        self.device["r1"] = 16  # second argument of the subbytes function

        self.device.start(self.device.functions["subbytes"],
                          0)  # rainbow launch the "subbytes" function

        # we prepare the leakage for this trace:
        leakage = np.fromiter(
            map(hamming_weight, self.device.sca_values_trace), dtype=np.uint8
        )  # a hamming_weight model is applied to the rainbow-generated leakage
        leakage = (np.random.normal(0, self.noise, len(leakage)) + leakage
                   )  # artificial noise is added to the leakage

        return Trace(leakage, self.value)


if __name__ == "__main__":

    container = RainbowSubBytesContainer(250)
    engine = CpaEngine(
        "cpa byte 5",
        lambda value, secret: sbox[value["plaintext"][5] ^ secret],
        range(256),
        solution=42,
    )
    session = Session(
        container,
        engine,
        output_method=ScoreProgressionOutputMethod(engine),
        output_steps=20,
    ).run()
Exemplo n.º 10
0
(For the rest of the tutorial, we will use a BasicAesSimulationContainer as trace Container)

"""

# First we need a Conainer, let's use BasicAesSimulationContainer. Say with 10000 traces, and the noise set to 1.
from lascar import BasicAesSimulationContainer

container = BasicAesSimulationContainer(10000, noise=1)
"""
The only required argument for a Session is the Container it works on.
(Other optional keywords argument will be presented later)
"""
from lascar import Session

session = Session(container)

# Session class implement a logger (like Container), whose level can be set by user:
session.logger.setLevel("WARN")
"""
The main method for Session class is the run() method. It consists in reading traces from the Container by batches.
The size of batches can be specified as an argument. 
Once the run() method is called, all traces are read and processed by the Engines registered by the Session.

Engines are classes dedicated to compute stuffs from side-channel traces. The Session distributes traces batches to all its Engines, for them to do their jobs.
Here a list of Engines already implemented in lascar:
- MeanEngine: compute the mean of all the traces leakages
- VarEngine: compute the varianc of all the traces leakages
- SnrEngine: compute Signal-to-Noise-Ratio from the traces leakages and a partitioning function appllied to the values.
- CpaEngine: compute Correlation Power Analysis from the traces leakages and a guess function appllied to the values.
- TTestEngine: compute Welch's T-Test from the traces leakages and a partitioning function appllied to the value