aboutsummaryrefslogtreecommitdiff
path: root/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'analysis')
-rw-r--r--analysis/countermeasures/collect_leia.ipynb349
1 files changed, 302 insertions, 47 deletions
diff --git a/analysis/countermeasures/collect_leia.ipynb b/analysis/countermeasures/collect_leia.ipynb
index 92d9367..4399c47 100644
--- a/analysis/countermeasures/collect_leia.ipynb
+++ b/analysis/countermeasures/collect_leia.ipynb
@@ -16,7 +16,7 @@
"outputs": [],
"source": [
"from pyecsca.sca.target.ectester import ECTesterTargetLEIA, KeypairEnum, ParameterEnum, CurveEnum, KeyEnum, KeyClassEnum, KeyBuildEnum, KeyAgreementEnum, SignatureEnum, TransformationEnum\n",
- "from pyecsca.ec.params import load_params_ectester\n",
+ "from pyecsca.ec.params import load_params_ectester, get_params\n",
"from pyecsca.sca.scope.picoscope_sdk import PS6000Scope\n",
"from pyecsca.sca.trace import Trace\n",
"from pyecsca.sca.trace.plot import plot_trace, plot_traces\n",
@@ -35,6 +35,19 @@
{
"cell_type": "code",
"execution_count": null,
+ "id": "3843d504-074a-4736-8c42-114ec63dab7d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyecsca.sca.trace.sampling import downsample_max, downsample_average, downsample_decimate\n",
+ "from pyecsca.sca.trace.process import rolling_mean, recenter, absolute, threshold\n",
+ "from pyecsca.sca.trace.filter import filter_lowpass\n",
+ "from pyecsca.sca.trace.edit import pad, trim"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"id": "865953a5-35ad-473e-a57f-f26368145987",
"metadata": {},
"outputs": [],
@@ -142,11 +155,18 @@
" scope.setup_capture(channel=\"B\", enable=True)\n",
"elif card == \"N2N9\":\n",
" # NXP JCOP v2.4.1R3\n",
- " actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=30_000_000)\n",
+ " # N9\n",
+ " actual_freq, n_samples = scope.setup_frequency(frequency=625_000_000, pretrig=0, posttrig=500_000_000)\n",
" scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
" scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.05, offset=-0.280, enable=True)\n",
" scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
" scope.setup_capture(channel=\"B\", enable=True)\n",
+ " # N2\n",
+ " #actual_freq, n_samples = scope.setup_frequency(frequency=50_000_000, pretrig=0, posttrig=40_000_000)\n",
+ " #scope.setup_channel(channel=\"A\", coupling=\"DC\", range=1, offset=0, enable=True)\n",
+ " #scope.setup_channel(channel=\"B\", coupling=\"DC_50\", range=0.1, offset=-0.18, enable=True)\n",
+ " #scope.setup_trigger(channel=\"A\", threshold=0.2, direction=\"rising\", delay=0, timeout=5000, enable=True)\n",
+ " #scope.setup_capture(channel=\"B\", enable=True)\n",
"elif card == \"N4\":\n",
" # NXP J3H145\n",
" # 15M for keygen\n",
@@ -203,6 +223,14 @@
]
},
{
+ "cell_type": "markdown",
+ "id": "088f806f-63ad-432a-a654-0d8a7d857187",
+ "metadata": {},
+ "source": [
+ "## Allocate"
+ ]
+ },
+ {
"cell_type": "code",
"execution_count": null,
"id": "27c4a7f7-3029-46d9-a3d5-3f4c0b56e37e",
@@ -218,6 +246,16 @@
{
"cell_type": "code",
"execution_count": null,
+ "id": "5b03d70f-1bf1-4e74-b9e4-b9d1591baee5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ectester.allocate_sig(SignatureEnum.ALG_ECDSA_SHA)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"id": "f952cf17-88f2-47d7-88f3-346c6cbd0572",
"metadata": {},
"outputs": [],
@@ -226,13 +264,22 @@
]
},
{
+ "cell_type": "markdown",
+ "id": "74a56989-91e7-44c8-ba9c-4c387c41de86",
+ "metadata": {},
+ "source": [
+ "## Set params"
+ ]
+ },
+ {
"cell_type": "code",
"execution_count": null,
"id": "4d67e5a3-79d3-4160-89c9-07f1cd697f52",
"metadata": {},
"outputs": [],
"source": [
- "params = load_params_ectester(\"curves/curves_full_order/cofactor256p313_full.csv\", \"affine\")"
+ "#params = get_params(\"secg\", \"secp256r1\", \"affine\")\n",
+ "params = load_params_ectester(\"../countermeasures/countermeasures/tests/comb/cofactor256p18446744073709551617_smallgen_fakeorder.csv\", \"affine\")"
]
},
{
@@ -259,6 +306,14 @@
]
},
{
+ "cell_type": "markdown",
+ "id": "7cd21c6a-e741-4e60-98ae-f7f58fa70a02",
+ "metadata": {},
+ "source": [
+ "## Generate"
+ ]
+ },
+ {
"cell_type": "code",
"execution_count": null,
"id": "26be2fb8-607c-4bce-8968-ba57938f9a89",
@@ -296,7 +351,7 @@
"metadata": {},
"outputs": [],
"source": [
- "trace_gen = scope.retrieve(\"B\", SampleType.Raw)"
+ "trace_gen = scope.retrieve(\"B\", SampleType.Volt)"
]
},
{
@@ -312,7 +367,149 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "08978417-6f39-4c40-a862-9ad43179dccc",
+ "id": "dd2a71ea-02ed-40d9-9268-6b47f304bac1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_trace(downsample_average(trace_gen, 1000))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e6a835a5-5904-4ec4-891a-ea4b2a57f1c9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def find_bumps(trace):\n",
+ " ds = downsample_average(trace, 1000)\n",
+ " ts = threshold(ds, 0.025)\n",
+ " prev = 0\n",
+ " previ = 0\n",
+ " total = []\n",
+ " big = []\n",
+ " for i, sample in enumerate(ts.samples):\n",
+ " if prev == 0 and sample == 1:\n",
+ " dist = i - previ\n",
+ " if dist > 2500 and total:\n",
+ " big.append(total)\n",
+ " total = []\n",
+ " if dist > 500:\n",
+ " l = [i]\n",
+ " total.append(l)\n",
+ " else:\n",
+ " total[-1].append(i)\n",
+ " previ = i\n",
+ " prev = sample\n",
+ " elif prev == 1 and sample == 0:\n",
+ " prev = sample\n",
+ " if total:\n",
+ " big.append(total)\n",
+ " s = []\n",
+ " for t in big:\n",
+ " seq = []\n",
+ " for l in t:\n",
+ " seq.append(str(len(l)))\n",
+ " s.append(\",\".join(seq))\n",
+ " return \"-\".join(s)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3bfb4b6b-f44d-43a4-b52f-fad6f978c301",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "find_bumps(trace_gen)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f795ea2f-c244-435f-b040-9c7e9ef9debd",
+ "metadata": {},
+ "source": [
+ "## Or set key"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9d3daeda-55d4-43d2-b33f-5c9caba41e67",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "priv = 0x3c984f3a459a6b8f1a5ece87a695d1b112b978024a9c56c1a12ade3500f29d8c\n",
+ "pub = params.curve.affine_multiply(params.generator, priv + 5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3f12952f-e9fd-44cf-817e-813385306145",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scope.arm()\n",
+ "sleep(2)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "34457f1e-de06-480e-9668-ef903f6d2b8c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ectester.set(KeypairEnum.KEYPAIR_LOCAL,\n",
+ " CurveEnum.external,\n",
+ " ParameterEnum.S | ParameterEnum.W,\n",
+ " {**ECTesterTargetLEIA.encode_parameters(ParameterEnum.S, priv),\n",
+ " **ECTesterTargetLEIA.encode_parameters(ParameterEnum.W, pub)})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a5117598-8cee-4af8-89f1-27af2360bd96",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scope.capture(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f8b68498-359a-47bd-ac20-c298b933cda7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trace_set = scope.retrieve(\"B\", SampleType.Volt)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0b2f0bb8-87a2-400a-90b3-b47b4181721b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_trace(trace_set)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2037aa6a-3533-4f20-b618-154aa040892c",
+ "metadata": {},
+ "source": [
+ "## ECDSA"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2af07d2a-d005-4a75-9a71-f2cd0e723335",
"metadata": {},
"outputs": [],
"source": [
@@ -323,23 +520,70 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "f4c1df63-4da3-4693-9aaa-217e4a9314f5",
+ "id": "c49b3f74-6229-463d-a4eb-468d7d98d4e4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "resp = ectester.ecdsa_sign(KeypairEnum.KEYPAIR_LOCAL,\n",
+ " True,\n",
+ " SignatureEnum.ALG_ECDSA_SHA,\n",
+ " b\"message\")\n",
+ "resp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b5078978-5867-438b-a4e1-7e4cc35d32e6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scope.capture(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "1b7d93be-78df-44a5-ae04-5db99db5a099",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "trace_ecdsa = scope.retrieve(\"B\", SampleType.Volt)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0abe66cf-b10f-49b8-a525-e606136303de",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_trace(trace_ecdsa)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "78f9c17b-c195-4c70-a5b7-79337de3112a",
+ "metadata": {},
+ "source": [
+ "## ECDH"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "08978417-6f39-4c40-a862-9ad43179dccc",
"metadata": {},
"outputs": [],
"source": [
- "with open(\"curves/cofactor_points/point_313.csv\", \"r\") as f:\n",
- " line = f.read()\n",
- " sx, sy = line.split(\",\")\n",
- " bx = bytes.fromhex(sx[2:])\n",
- " by = bytes.fromhex(sy[2:])\n",
- " point = bytes([0x04]) + bx + by\n",
- " print(point.hex())"
+ "scope.arm()\n",
+ "sleep(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "ad17301a-902f-48e9-936e-f553a1a8f006",
+ "id": "d7626f39-53e4-41a7-afe2-d89e15f6a0c9",
"metadata": {},
"outputs": [],
"source": [
@@ -347,7 +591,7 @@
" True,\n",
" TransformationEnum.NONE,\n",
" KeyAgreementEnum.ALG_EC_SVDP_DH,\n",
- " point) # pubkey as bytes"
+ " bytes(params.generator))"
]
},
{
@@ -381,131 +625,142 @@
]
},
{
- "cell_type": "code",
- "execution_count": null,
- "id": "6c46be4f-8901-4b29-a30e-71ac28bafcd9",
+ "cell_type": "markdown",
+ "id": "309e8d83-771b-4783-9bb5-474c9d5bf8ec",
"metadata": {},
- "outputs": [],
"source": [
- "from pyecsca.sca.trace.edit import pad, trim"
+ "## Misc"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "1d4b775e-fa7d-48aa-bb24-bec7450c8114",
+ "id": "a29e460b-cca7-4d28-b2e2-3920b0870628",
"metadata": {},
"outputs": [],
"source": [
- "trim?"
+ "ectester.cleanup()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "7164dab5-090f-4a6a-9ce6-8e252e71af76",
+ "id": "264b4653-023c-4a39-8970-270c2f0d42c6",
"metadata": {},
"outputs": [],
"source": [
- "plot_traces(ecdh_ok, pad(trim(trace_ecdh, 0, len(trace_ecdh) -363700), (363700, 0)))"
+ "ectester.disconnect()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "0395b2aa-3c00-4068-8179-039e7e5ad039",
+ "id": "1d706782-7124-4879-8198-407e45f131ff",
"metadata": {},
"outputs": [],
"source": [
- "from scipy import signal\n",
- "import numpy as np"
+ "scope.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a5ed4ed6-7732-41a6-b6a9-61e76851f468",
+ "metadata": {},
+ "source": [
+ "### Frequency analysis"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "1b63e6d3-8488-4c13-91fa-388318e8e1bc",
+ "id": "60139124-f51c-4e1c-858c-e46731d38bde",
"metadata": {},
"outputs": [],
"source": [
- "corr = signal.correlate(trace_ecdh.samples, trace_ecdh.samples, mode=\"full\")\n",
- "lags = signal.correlation_lags(trace_ecdh.samples.size, trace_ecdh.samples.size, mode=\"full\")\n",
- "lag = lags[np.argmax(corr)]\n"
+ "plot_trace(filter_lowpass(trim(trace_ecdsa, 55_000_000, 56_000_000), 625000000, 250_000_000))"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "f6fbd522-c9db-4dbc-bd05-109ba3d3fdf9",
+ "id": "031d0c18-7408-46e0-8853-cc9e485902d1",
"metadata": {},
"outputs": [],
"source": [
- "plot_trace(Trace(corr))"
+ "from scipy.signal import periodogram\n",
+ "from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "5a910cc9-80bd-4c74-a36a-56804aea42e1",
+ "id": "40be47b6-b08a-49e2-b40e-2b5b6ca6be13",
"metadata": {},
"outputs": [],
- "source": []
+ "source": [
+ "%matplotlib widget"
+ ]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "195ed167-8925-44c9-b0fb-6e207f8fdf8a",
+ "id": "65aa1eb2-2694-4697-a2cd-869272218b6a",
"metadata": {},
"outputs": [],
"source": [
- "ectester.cleanup()"
+ "f, Pxx_den = periodogram(recenter(trim(trace_ecdsa, 30_000_000, 500_000_000)).samples, 625000000)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "264b4653-023c-4a39-8970-270c2f0d42c6",
+ "id": "c52d798b-d40b-4914-908a-3b34c51a2084",
"metadata": {},
"outputs": [],
"source": [
- "ectester.disconnect()"
+ "plt.semilogy(f, Pxx_den)\n",
+ "#plt.ylim([1e-7, 1e2])\n",
+ "plt.xlabel('frequency [Hz]')\n",
+ "plt.ylabel('PSD [V**2/Hz]')\n",
+ "plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "1d706782-7124-4879-8198-407e45f131ff",
+ "id": "197fd1b9-7d91-4f23-b89d-e68727be36d7",
"metadata": {},
"outputs": [],
"source": [
- "scope.close()"
+ "from scipy.signal import find_peaks"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "768a8fe0-27ec-4678-a66a-66e7680fd6c8",
+ "id": "1fd46ee6-de5e-45f6-bee0-e3ead0029aca",
"metadata": {},
"outputs": [],
"source": [
- "from pyecsca.sca.trace.process import rolling_mean, recenter\n",
- "from pyecsca.sca.trace.filter import filter_lowpass"
+ "pks = find_peaks(Pxx_den, height=1.52e-7)"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "d93ce9cd-1516-4e32-9fed-94a19fac23f4",
+ "id": "3b03f991-7f89-43df-9726-13515ae78c26",
"metadata": {},
"outputs": [],
"source": [
- "from pyecsca.sca.trace.plot import plot_trace, plot_traces"
+ "len(pks[0])\n",
+ "for pk in f[pks[0]]:\n",
+ " print(int(pk))"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "45f2a8ab-af15-46f9-904e-76e5eeb08978",
+ "id": "d4f527fe-96f3-4e90-b802-3d063beb619c",
"metadata": {},
"outputs": [],
"source": []