diff options
| author | J08nY | 2020-02-08 23:23:02 +0100 |
|---|---|---|
| committer | J08nY | 2020-02-08 23:23:02 +0100 |
| commit | 2b8f3752505c3a03f617534ebfadd7fb70e09ba2 (patch) | |
| tree | f1eb76b4eca348ae763e2578ef0e13d2b8a1d74b | |
| parent | 59b09851d4452448ffd9100aca2335f2424885e0 (diff) | |
| download | pyecsca-2b8f3752505c3a03f617534ebfadd7fb70e09ba2.tar.gz pyecsca-2b8f3752505c3a03f617534ebfadd7fb70e09ba2.tar.zst pyecsca-2b8f3752505c3a03f617534ebfadd7fb70e09ba2.zip | |
| -rw-r--r-- | .travis.yml | 3 | ||||
| -rw-r--r-- | LICENSE | 2 | ||||
| -rw-r--r-- | Makefile | 9 | ||||
| -rw-r--r-- | Pipfile | 1 | ||||
| -rw-r--r-- | README.md | 7 | ||||
| -rw-r--r-- | docs/Makefile | 4 | ||||
| -rw-r--r-- | docs/index.rst | 12 | ||||
| -rw-r--r-- | pyecsca/ec/__init__.py | 1 | ||||
| -rw-r--r-- | pyecsca/ec/coordinates.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/curves.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/formula.py | 7 | ||||
| -rw-r--r-- | pyecsca/ec/model.py | 4 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/point.py | 2 | ||||
| -rw-r--r-- | pyecsca/sca/__init__.py | 2 | ||||
| -rw-r--r-- | pyecsca/sca/scope/__init__.py | 4 | ||||
| -rw-r--r-- | pyecsca/sca/scope/chipwhisperer.py | 31 | ||||
| -rw-r--r-- | pyecsca/sca/scope/picoscope_sdk.py | 14 | ||||
| -rw-r--r-- | pyecsca/sca/target/__init__.py | 1 | ||||
| -rw-r--r-- | pyecsca/sca/trace/__init__.py | 4 | ||||
| -rw-r--r-- | pyecsca/sca/trace/align.py | 1 | ||||
| -rw-r--r-- | pyecsca/sca/trace/match.py | 1 | ||||
| -rw-r--r-- | pyecsca/sca/trace/test.py | 2 | ||||
| -rw-r--r-- | pyecsca/sca/trace_set/__init__.py | 4 | ||||
| -rw-r--r-- | setup.py | 2 |
25 files changed, 88 insertions, 36 deletions
diff --git a/.travis.yml b/.travis.yml index 0bac320..3056665 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,10 +26,11 @@ before_install: install: - pip install codecov - - pip install -e ".[picoscope_sdk, picoscope_alt, chipwhisperer, test, typecheck]" + - pip install -e ".[picoscope_sdk, picoscope_alt, chipwhisperer, test, dev]" script: - make -i typecheck + - make -i codestyle - make test after_success: @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2019 +Copyright (c) 2018-2020 Jan Jancar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,11 @@ test-all: typecheck: mypy pyecsca --ignore-missing-imports -.PHONY: test test-plots test-all typecheck
\ No newline at end of file +codestyle: + flake8 --ignore=E501,F405,F403,F401,E126 pyecsca + +docs: + $(MAKE) -C docs apidoc + $(MAKE) -C docs html + +.PHONY: test test-plots test-all typecheck codestyle docs
\ No newline at end of file @@ -7,6 +7,7 @@ verify_ssl = true nose2 = "*" green = "*" mypy = "*" +flake8 = "*" sphinx = "*" sphinx-autodoc-typehints = "*" coverage = "*" @@ -20,6 +20,10 @@ and ECC simulation in the [*pyecsca.ec*](pyecsca/ec) package. - [atpublic](https://public.readthedocs.io/) - [fastdtw](https://github.com/slaypni/fastdtw) - [asn1crypto](https://github.com/wbond/asn1crypto) + - **Optionally**: + - [picosdk](https://github.com/picotech/picosdk-python-wrappers/) + - [picoscope](https://github.com/colinoflynn/pico-python) + - [chipwhisperer](https://github.com/newaetech/chipwhisperer) *pyecsca* contains data from the [Explicit-Formulas Database](https://www.hyperelliptic.org/EFD/index.html) by Daniel J. Bernstein and Tanja Lange. The data was partially changed, to make working with it easier. @@ -31,6 +35,7 @@ It also supports working with [Riscure](https://www.riscure.com) Inspector trace - [nose2](https://nose2.readthedocs.io) - [green](https://github.com/CleanCut/green) - [mypy](http://mypy-lang.org/) + - [flake8](https://flake8.pycqa.org/) - [coverage](https://coverage.readthedocs.io/) ### Docs @@ -43,7 +48,7 @@ It also supports working with [Riscure](https://www.riscure.com) Inspector trace MIT License - Copyright (c) 2018-2019 + Copyright (c) 2018-2020 Jan Jancar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/Makefile b/docs/Makefile index 689e069..4f2a169 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -14,8 +14,8 @@ help: apidoc: mkdir -p api/codegen/ - sphinx-apidoc ../pyecsca/ --implicit-namespaces --ext-autodoc -f -e -o api/ - sphinx-apidoc ../../pyecsca-codegen/pyecsca/ --implicit-namespaces --ext-autodoc --no-toc -f -e -o api/codegen/ + sphinx-apidoc ../pyecsca/ --implicit-namespaces --ext-autodoc -M -f -e -o api/ + sphinx-apidoc ../../pyecsca-codegen/pyecsca/ --implicit-namespaces --ext-autodoc -M -no-toc -f -e -o api/codegen/ echo " codegen/pyecsca.codegen" >> api/modules.rst .PHONY: help apidoc Makefile diff --git a/docs/index.rst b/docs/index.rst index 795713b..49bab42 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,6 +39,11 @@ Requirements - atpublic_ - fastdtw_ - asn1crypto_ + - **Optionally**: + + - picosdk_ + - picoscope_ + - chipwhisperer_ *pyecsca* contains data from the `Explicit-Formulas Database`_ by Daniel J. Bernstein and Tanja Lange. @@ -51,6 +56,7 @@ Testing - nose2_ - green_ - mypy_ + - flake8 - coverage_ Docs @@ -64,7 +70,7 @@ License MIT License - Copyright (c) 2018-2019 + Copyright (c) 2018-2020 Jan Jancar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -93,9 +99,13 @@ this support is very appreciated. .. _atpublic: https://public.readthedocs.io/ .. _fastdtw: https://github.com/slaypni/fastdtw .. _asn1crypto: https://github.com/wbond/asn1crypto +.. _picosdk: https://github.com/picotech/picosdk-python-wrappers/ +.. _picoscope: https://github.com/colinoflynn/pico-python +.. _chipwhisperer: https://github.com/newaetech/chipwhisperer .. _nose2: https://nose2.readthedocs.io .. _green: https://github.com/CleanCut/green .. _mypy: http://mypy-lang.org/ +.. _flake8: https://flake8.pycqa.org/ .. _coverage: https://coverage.readthedocs.io/ .. _sphinx: https://www.sphinx-doc.org/ .. _sphinx-autodoc-typehints: https://pypi.org/project/sphinx-autodoc-typehints/ diff --git a/pyecsca/ec/__init__.py b/pyecsca/ec/__init__.py index e69de29..a1fa2ce 100644 --- a/pyecsca/ec/__init__.py +++ b/pyecsca/ec/__init__.py @@ -0,0 +1 @@ +"""Package for handling Elliptic Curves.""" diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py index e082a41..89452c9 100644 --- a/pyecsca/ec/coordinates.py +++ b/pyecsca/ec/coordinates.py @@ -88,7 +88,7 @@ class EFDCoordinateModel(CoordinateModel): code = parse(line[11:].replace("^", "**"), mode="exec") self.satisfying.append(code) except SyntaxError: - #code = parse(line[11:].replace("=", "==").replace("^", "**"), mode="eval") + # code = parse(line[11:].replace("=", "==").replace("^", "**"), mode="eval") pass elif line.startswith("parameter"): self.parameters.append(line[10:]) diff --git a/pyecsca/ec/curves.py b/pyecsca/ec/curves.py index de919b8..7fcfcbd 100644 --- a/pyecsca/ec/curves.py +++ b/pyecsca/ec/curves.py @@ -85,7 +85,7 @@ SHORT_WEIERSTRASS: Mapping[str, Mapping[str, Any]] = { "g": (0x7b6aa5d85e572983e6fb32a7cdebc140, 0x27b6916a894d3aee7106fe805fc34b44), "n": 0x3fffffff7fffffffbe0024720613b5a3, - "h":0x4}, + "h": 0x4}, "secp160k1": { "p": 0xfffffffffffffffffffffffffffffffeffffac73, "a": 0x0000000000000000000000000000000000000000, diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py index 2da6ad5..aeed4a6 100644 --- a/pyecsca/ec/formula.py +++ b/pyecsca/ec/formula.py @@ -1,6 +1,6 @@ from ast import parse, Expression, Mult, Add, Sub, Pow, Div -from typing import List, Set, Any, ClassVar, MutableMapping from itertools import product +from typing import List, Set, Any, ClassVar, MutableMapping from pkg_resources import resource_stream from public import public @@ -68,6 +68,7 @@ class Formula(object): """Number of additions and subtractions.""" return len(list(filter(lambda op: isinstance(op.operator, (Add, Sub)), self.code))) + class EFDFormula(Formula): def __init__(self, path: str, name: str, coordinate_model: Any): @@ -116,7 +117,8 @@ class EFDFormula(Formula): @property def outputs(self): return set(var + str(i) for var, i in product(self.coordinate_model.variables, - range(self.output_index, self.output_index + self.num_outputs))) + range(self.output_index, + self.output_index + self.num_outputs))) def __eq__(self, other): if not isinstance(other, EFDFormula): @@ -126,6 +128,7 @@ class EFDFormula(Formula): def __hash__(self): return hash(self.name) + hash(self.coordinate_model) + @public class AdditionFormula(Formula): shortname = "add" diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py index c8a9b46..a313a00 100644 --- a/pyecsca/ec/model.py +++ b/pyecsca/ec/model.py @@ -20,8 +20,8 @@ class CurveModel(object): to_weierstrass: List[Module] from_weierstrass: List[Module] - #TODO: move the base_formulas into methods, operatin on affine points? - # Also to_weierstrass anf from_weierstrass. + # TODO: move the base_formulas into methods, operatin on affine points? + # Also to_weierstrass anf from_weierstrass. # TODO: __eq__ diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py index ef74bc8..5a76a18 100644 --- a/pyecsca/ec/mult.py +++ b/pyecsca/ec/mult.py @@ -32,7 +32,7 @@ class ScalarMultiplier(object): formula is not None)) != 1: raise ValueError self.short_circuit = short_circuit - self.formulas = {k:v for k, v in formulas.items() if v is not None} + self.formulas = {k: v for k, v in formulas.items() if v is not None} def _add(self, one: Point, other: Point) -> Point: if "add" not in self.formulas: diff --git a/pyecsca/ec/point.py b/pyecsca/ec/point.py index 368dd0d..b5ba10b 100644 --- a/pyecsca/ec/point.py +++ b/pyecsca/ec/point.py @@ -35,7 +35,7 @@ class Point(object): for s in self.coordinate_model.satisfying: try: ops.add(CodeOp(s)) - except: + except Exception: pass affine_model = AffineCoordinateModel(self.coordinate_model.curve_model) result_variables = set(map(lambda x: x.result, ops)) diff --git a/pyecsca/sca/__init__.py b/pyecsca/sca/__init__.py index 4e5c985..3117331 100644 --- a/pyecsca/sca/__init__.py +++ b/pyecsca/sca/__init__.py @@ -1,3 +1,5 @@ +"""Package for Side-Channel Analysis.""" + from .scope import * from .target import * from .trace import * diff --git a/pyecsca/sca/scope/__init__.py b/pyecsca/sca/scope/__init__.py index d11ed82..b609e94 100644 --- a/pyecsca/sca/scope/__init__.py +++ b/pyecsca/sca/scope/__init__.py @@ -1,3 +1,5 @@ +"""Package for handling oscilloscopes for measurement of power/EM traces.""" + from typing import Type from .base import * @@ -30,9 +32,11 @@ except ImportError: PicoScope: Type[Scope] if has_picoscope: from .picoscope_alt import * + PicoScope = PicoScopeAlt elif has_picosdk: from .picoscope_sdk import * + PicoScope = PicoScopeSdk if has_chipwhisperer: diff --git a/pyecsca/sca/scope/chipwhisperer.py b/pyecsca/sca/scope/chipwhisperer.py index 60fe7cf..8f5590d 100644 --- a/pyecsca/sca/scope/chipwhisperer.py +++ b/pyecsca/sca/scope/chipwhisperer.py @@ -1,47 +1,56 @@ -from typing import Optional, Tuple, Sequence +from typing import Optional, Tuple, Sequence, Set import numpy as np -from chipwhisperer.capture.scopes.base import ScopeTemplate +from chipwhisperer.capture.scopes.OpenADC import OpenADC from public import public from .base import Scope + @public -class ChipWhispererScope(Scope): +class ChipWhispererScope(Scope): # pragma: no cover """A ChipWhisperer based scope.""" - def __init__(self, scope: ScopeTemplate): + def __init__(self, scope: OpenADC): self.scope = scope + self.triggers: Set[str] = set() def open(self) -> None: self.scope.con() @property def channels(self) -> Sequence[str]: - return ["tio1", "tio2", "tio3", "tio4"] + return [] def setup_frequency(self, frequency: int, samples: int) -> Tuple[int, int]: - pass + self.scope.clock.clkgen_freq = frequency + self.scope.samples = samples + return self.scope.clock.freq_ctr, self.scope.samples def setup_channel(self, channel: str, coupling: str, range: float, enable: bool) -> None: pass def setup_trigger(self, channel: str, threshold: float, direction: str, delay: int, timeout: int, enable: bool) -> None: - pass + if enable: + self.triggers.add(channel) + elif channel in self.triggers: + self.triggers.remove(channel) + self.scope.adc.basic_mode = direction + self.scope.trigger.triggers = " OR ".join(self.triggers) def setup_capture(self, channel: str, enable: bool) -> None: pass def arm(self) -> None: - pass + self.scope.arm() def capture(self, channel: str, timeout: Optional[int] = None) -> Optional[np.ndarray]: - pass + self.scope.capture() + return self.scope.get_last_trace() def stop(self) -> None: pass def close(self) -> None: - pass - + self.scope.dis() diff --git a/pyecsca/sca/scope/picoscope_sdk.py b/pyecsca/sca/scope/picoscope_sdk.py index d44d8c8..e552188 100644 --- a/pyecsca/sca/scope/picoscope_sdk.py +++ b/pyecsca/sca/scope/picoscope_sdk.py @@ -1,6 +1,6 @@ import ctypes -from time import time_ns, sleep from math import log2, floor +from time import time_ns, sleep from typing import Mapping, Optional, MutableMapping, Union, Tuple import numpy as np @@ -22,7 +22,7 @@ def adc2volt(adc: Union[np.ndarray, ctypes.c_int16], def volt2adc(volt: Union[np.ndarray, float], volt_range: float, adc_minmax: int) -> Union[ - np.ndarray, ctypes.c_int16]: # pragma: no cover + np.ndarray, ctypes.c_int16]: # pragma: no cover if isinstance(volt, float): return ctypes.c_int16(int((volt / volt_range) * adc_minmax)) return (volt / volt_range) * adc_minmax @@ -130,12 +130,14 @@ class PicoScopeSdk(Scope): # pragma: no cover if channel in self.buffers: del self.buffers[channel] buffer = (ctypes.c_int16 * self.samples)() - assert_pico_ok(self.__dispatch_call("SetDataBuffer", self.handle, self.CHANNELS[channel], - ctypes.byref(buffer), self.samples)) + assert_pico_ok( + self.__dispatch_call("SetDataBuffer", self.handle, self.CHANNELS[channel], + ctypes.byref(buffer), self.samples)) self.buffers[channel] = buffer else: - assert_pico_ok(self.__dispatch_call("SetDataBuffer", self.handle, self.CHANNELS[channel], - None, self.samples)) + assert_pico_ok( + self.__dispatch_call("SetDataBuffer", self.handle, self.CHANNELS[channel], + None, self.samples)) del self.buffers[channel] def arm(self): diff --git a/pyecsca/sca/target/__init__.py b/pyecsca/sca/target/__init__.py index e69de29..750f885 100644 --- a/pyecsca/sca/target/__init__.py +++ b/pyecsca/sca/target/__init__.py @@ -0,0 +1 @@ +"""Package for communicating with targets of measurement.""" diff --git a/pyecsca/sca/trace/__init__.py b/pyecsca/sca/trace/__init__.py index 62f2864..696e387 100644 --- a/pyecsca/sca/trace/__init__.py +++ b/pyecsca/sca/trace/__init__.py @@ -1,3 +1,5 @@ +"""Package for manipulating traces.""" + from .align import * from .combine import * from .edit import * @@ -6,4 +8,4 @@ from .match import * from .process import * from .sampling import * from .test import * -from .trace import *
\ No newline at end of file +from .trace import * diff --git a/pyecsca/sca/trace/align.py b/pyecsca/sca/trace/align.py index ff586ab..643efcf 100644 --- a/pyecsca/sca/trace/align.py +++ b/pyecsca/sca/trace/align.py @@ -121,6 +121,7 @@ def align_offset(reference: Trace, *traces: Trace, :return: """ reference_part = reference.samples[reference_offset: reference_offset + reference_length] + def align_func(trace): length = len(trace.samples) best_distance = 0 diff --git a/pyecsca/sca/trace/match.py b/pyecsca/sca/trace/match.py index ba69026..3b4daed 100644 --- a/pyecsca/sca/trace/match.py +++ b/pyecsca/sca/trace/match.py @@ -32,6 +32,7 @@ def match_pattern(trace: Trace, pattern: Trace, threshold: float = 0.8) -> List[ filtered_peaks.append(peak - half) return filtered_peaks + @public def match_part(trace: Trace, offset: int, length: int) -> List[int]: return match_pattern(trace, trim(trace, offset, offset + length)) diff --git a/pyecsca/sca/trace/test.py b/pyecsca/sca/trace/test.py index 92cda68..f2cfb33 100644 --- a/pyecsca/sca/trace/test.py +++ b/pyecsca/sca/trace/test.py @@ -32,7 +32,7 @@ def welch_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Opti @public def student_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[ - CombinedTrace]: + CombinedTrace]: """ Perform the Students's t-test sample wise on two sets of traces `first_set` and `second_set`. Useful for Test Vector Leakage Analysis (TVLA). diff --git a/pyecsca/sca/trace_set/__init__.py b/pyecsca/sca/trace_set/__init__.py index 517b3b7..cdede67 100644 --- a/pyecsca/sca/trace_set/__init__.py +++ b/pyecsca/sca/trace_set/__init__.py @@ -1,3 +1,5 @@ +"""Package for manipulating, reading and writing trace sets.""" + from .base import * from .inspector import * -from .chipwhisperer import *
\ No newline at end of file +from .chipwhisperer import * @@ -37,7 +37,7 @@ setup( "picoscope_sdk": ["picosdk"], "picoscope_alt": ["picoscope"], "chipwhisperer": ["chipwhisperer"], - "typecheck": ["mypy"], + "dev": ["mypy", "flake8"], "test": ["nose2", "parameterized", "green", "coverage"] } ) |
