aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/sca/trace_set/chipwhisperer.py
blob: 1a66db8cadf537fc8d51b86c8405b83a6341214b (plain) (blame)
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
from configparser import ConfigParser
from itertools import zip_longest
from os.path import exists, isfile, join, basename, dirname
from pathlib import Path
from typing import Union, BinaryIO

import numpy as np
from public import public

from pyecsca.sca.trace_set.base import TraceSet
from pyecsca.sca.trace import Trace


@public
class ChipWhispererTraceSet(TraceSet):
    """ChipWhisperer trace set (native) format."""

    @classmethod
    def read(
        cls, input: Union[str, Path, bytes, BinaryIO], **kwargs
    ) -> "ChipWhispererTraceSet":
        if isinstance(input, (str, Path)):
            traces, kws = ChipWhispererTraceSet.__read(input)
            return ChipWhispererTraceSet(*traces, **kws)
        else:
            raise ValueError

    @classmethod
    def inplace(
        cls, input: Union[str, Path, bytes, BinaryIO], **kwargs
    ) -> "ChipWhispererTraceSet":
        raise NotImplementedError

    def write(self, output: Union[str, Path, BinaryIO]):
        raise NotImplementedError

    @classmethod
    def __read(cls, full_path):
        file_name = basename(full_path)
        if not file_name.startswith("config_") or not file_name.endswith(".cfg"):
            raise ValueError
        path = dirname(full_path)
        name = file_name[7:-4]
        data = ChipWhispererTraceSet.__read_data(path, name)
        traces = []
        for samples, key, textin, textout in zip_longest(
            data["traces"], data["keylist"], data["textin"], data["textout"]
        ):
            traces.append(
                Trace(samples, {"key": key, "textin": textin, "textout": textout})
            )
        del data["traces"]
        del data["keylist"]
        del data["textin"]
        del data["textout"]
        config = ChipWhispererTraceSet.__read_config(path, name)
        return traces, {**data, **config}

    @classmethod
    def __read_data(cls, path, name):
        types = {
            "keylist": None,
            "knownkey": None,
            "textin": None,
            "textout": None,
            "traces": None,
        }
        for type in types:
            type_path = join(path, name + type + ".npy")
            if exists(type_path) and isfile(type_path):
                types[type] = np.load(type_path, allow_pickle=True)
        return types

    @classmethod
    def __read_config(cls, path, name):
        config_path = join(path, "config_" + name + ".cfg")
        if exists(config_path) and isfile(config_path):
            config = ConfigParser()
            config.read(config_path)
            return config["Trace Config"]
        else:
            return {}

    def __repr__(self):
        return "ChipWhispererTraceSet()"