DOI: 10.5281/zenodo.3878833
title: CVE-2019-1547: research data and tooling

description: This dataset and software tool are for reproducing the research results related to CVE-2019-1547, resulting from the manuscript "Certified Side Channels". The data was used to produce Figure 4 in the paper and is part of the remote timing attack data in Section 4.1. Data description The file <code>timings.json</code> contains a single JSON array. Each entry is a dictionary representation of one digital signature. A description of the dictionary fields follows. <code>hash_function</code>: string denoting the hash function for the digital signature. <code>hash</code>: the output of said hash function, i.e. hash of the message digitally signed. <code>order</code>: the order of the generator. <code>private_key</code>: the ECDSA private key. <code>public_key</code>: the corresponding public key. <code>sig_r</code>: the <code>r</code> component of the ECDSA signature. <code>sig_s</code>: the <code>s</code> component of the ECDSA signature. <code>sig_nonce</code>: the ground truth nonce generated during ECDSA signing. <code>nonce_bits</code>: the ground truth number of bits in said nonce. <code>latency</code>: the measured wall clock time (CPU clock cycles) to produce the digital signature. Prerequisites OpenSSL 1.1.1a, 1.1.1b, or 1.1.1.c. <pre><code>sudo apt install python-ijson jq</code></pre> Data setup Extract the JSON: <pre><code>tar xf timings.tar.xz</code></pre> Key setup Generate the public key (<code>public.pem</code> here) from the provided private key (<code>private.pem</code> here): <pre><code>$ openssl pkey -in private.pem -pubout -out public.pem</code></pre> Examine the keys if you want. <pre><code>$ openssl pkey -in private.pem -text -noout $ openssl pkey -in public.pem -text -noout -pubin</code></pre> Example: Verify key material <pre><code>$ grep --max-count=1 'private_key' timings.json "private_key":"0x6b76cc816dce9a8ebc6ff190bcf0555310d1fb0824047f703f627f338bcf5435", $ grep --max-count=1 'public_key' timings.json "public_key":"0x04396d7ae480016df31f84f80439e320b0638e024014a5d8e14923eea76948afb25a321ccadabd8a4295a1e8823879b9b65369bd49d337086850b3c799c7352828", $ openssl pkey -in private.pem -text -noout Private-Key: (256 bit) priv: 6b:76:cc:81:6d:ce:9a:8e:bc:6f:f1:90:bc:f0:55: 53:10:d1:fb:08:24:04:7f:70:3f:62:7f:33:8b:cf: 54:35 pub: 04:39:6d:7a:e4:80:01:6d:f3:1f:84:f8:04:39:e3: 20:b0:63:8e:02:40:14:a5:d8:e1:49:23:ee:a7:69: 48:af:b2:5a:32:1c:ca:da:bd:8a:42:95:a1:e8:82: 38:79:b9:b6:53:69:bd:49:d3:37:08:68:50:b3:c7: 99:c7:35:28:28 Field Type: prime-field Prime: 00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00: 00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff A: 00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00: 00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:fc B: 5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86: bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2: 60:4b Generator (uncompressed): 04:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4: 40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8: 98:c2:96:4f:e3:42:e2:fe:1a:7f:9b:8e:e7:eb:4a: 7c:0f:9e:16:2b:ce:33:57:6b:31:5e:ce:cb:b6:40: 68:37:bf:51:f5 Order: 00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff: ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc: 63:25:51 Cofactor: 0 Seed: c4:9d:36:08:86:e7:04:93:6a:66:78:e1:13:9d:26: b7:81:9f:7e:90</code></pre> Three things to note in the output: The private key bytes match (<code>private_key</code> and <code>priv</code> byte strings are equal) The public key bytes match (<code>public_key</code> and <code>pub</code> byte strings are equal) This is an explicit parameters key, with the <code>Cofactor</code> parameter missing or zero, as described in the manuscript. Example: Extract a single entry Here we use the python script <code>pickone.py</code> to extract the entry at index 2 (starting from 0). <pre><code>$ python2 pickone.py timings.json 2 | jq . &gt; 2.json $ cat 2.json { "public_key": "0x04396d7ae480016df31f84f80439e320b0638e024014a5d8e14923eea76948afb25a321ccadabd8a4295a1e8823879b9b65369bd49d337086850b3c799c7352828", "private_key": "0x6b76cc816dce9a8ebc6ff190bcf0555310d1fb0824047f703f627f338bcf5435", "hash": "0xf36d0481e14869fc558b39ae4c747bc6c089a0271b23cfd92bc0b8aa7ed2c3aa", "latency": 21565213, "nonce_bits": 253, "sig_nonce": "0x1b88c7802ea000ccb21116575c38004579b55f1f9c4f81ed321896b1e1034237", "hash_function": "sha256", "sig_s": "0x8c83417891547224006723169de9745a81fa8de7176428e1cd8e6110408f45da", "sig_r": "0xf922d9ba4f65d207300cc7eaaa15564e60a2b1f208d1389057ff1a1ec52dc653", "order": "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" }</code></pre> Example: Dump hash to binary file Extract the <code>hash</code> field from the target JSON and dump it as binary. <pre><code>$ sed -n 's/^ "hash": "0x\(.*\)",$/\1/p' 2.json | xxd -r -p &gt; 2.hash $ xxd -g1 2.hash 00000000: f3 6d 04 81 e1 48 69 fc 55 8b 39 ae 4c 74 7b c6 .m...Hi.U.9.Lt{. 00000010: c0 89 a0 27 1b 23 cf d9 2b c0 b8 aa 7e d2 c3 aa ...'.#..+...~...</code></pre> Note the <code>xxd</code> output matches the <code>hash</code> byte string from the target JSON. Example: Dump signature to DER The <code>hex2der.sh</code> script takes as an argument the target JSON filename, and outputs the DER-encoded ECDSA signature to stdout by extracting the <code>sig_r</code> and <code>sig_s</code> fields from the target JSON. <pre><code>$ ./hex2der.sh 2.json &gt; 2.der $ openssl asn1parse -in 2.der -inform DER 0:d=0 hl=2 l= 70 cons: SEQUENCE 2:d=1 hl=2 l= 33 prim: INTEGER :F922D9BA4F65D207300CC7EAAA15564E60A2B1F208D1389057FF1A1EC52DC653 37:d=1 hl=2 l= 33 prim: INTEGER :8C83417891547224006723169DE9745A81FA8DE7176428E1CD8E6110408F45DA</code></pre> Note the <code>asn1parse</code> output contains a sequence with two integers, matching the <code>sig_r</code> and <code>sig_s</code> fields from the target JSON. Example: Verify the signature We use <code>pkeyutl</code> here to verify the raw hash directly, in contrast to <code>dgst</code> that will only verify by recomputing the hash itself. <pre><code>$ openssl pkeyutl -in 2.hash -inkey public.pem -pubin -verify -sigfile 2.der Signature Verified Successfully</code></pre> Note it fails for other hashes (messages), a fundamental security property for digital signatures: <pre><code>$ dd if=/dev/urandom of=bad.hash bs=1 count=32 32+0 records in 32+0 records out 32 bytes copied, 0.00129336 s, 24.7 kB/s $ openssl pkeyutl -in bad.hash -inkey public.pem -pubin -verify -sigfile 2.der Signature Verification Failure</code></pre> Example: Statistics The <code>stats.py</code> script shows how to extract the desired fields from the JSON. It computes the median latency over each nonce bit length. <pre><code>$ python2 stats.py timings.json Len Median 238 20592060 239 20251286 240 20706144 241 20658896 242 20820100 243 20762304 244 20907332 245 20973536 246 20972244 247 21057788 248 21115419 249 21157888 250 21210560 251 21266378 252 21322146 253 21370608 254 21425454 255 21479105 256 21532532</code></pre> You can verify these medians are consistent with Figure 4 in the paper. The <code>stats.py</code> script can be easily modified for more advanced analysis. Credits Authors Cesar Pereida García (Tampere University, Tampere, Finland) Sohaib ul Hassan (Tampere University, Tampere, Finland) Iaroslav Gridin (Tampere University, Tampere, Finland) Nicola Tuveri (Tampere University, Tampere, Finland) Alejandro Cabrera Aldaya (Tampere University, Tampere, Finland) Billy Bob Brumley (Tampere University, Tampere, Finland) Funding This project has received funding from the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 804476). License This project is distributed under MIT license.