core+legacy: rework code styling checks

pull/89/head
Pavol Rusnak 5 years ago
parent 9f8ebcf183
commit 8b06598474
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

1
.gitmodules vendored

@ -23,6 +23,7 @@
[submodule "legacy/vendor/nanopb"]
path = legacy/vendor/nanopb
url = https://github.com/nanopb/nanopb.git
ignore = untracked
[submodule "legacy/vendor/QR-Code-generator"]
path = legacy/vendor/QR-Code-generator
url = https://github.com/nayuki/QR-Code-generator.git

@ -0,0 +1,24 @@
## help commands:
help: ## show this help
@awk -f ./tools/help.awk $(MAKEFILE_LIST)
## style commands:
style_check: ## run code style check on application sources and tests
flake8 --version
isort --version | awk '/VERSION/{print $$2}'
black --version
flake8 $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
isort --check-only $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
black --check $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
style: ## apply code style on application sources and tests
isort $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
black $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
cstyle_check: ## run code style check on low-level C code
./tools/clang-format-check $(shell find -type f -name '*.c' -o -name '*.h' | grep -f ./tools/style.c.include | grep -v -f ./tools/style.c.exclude )
cstyle: ## apply code style on low-level C code
clang-format -i $(shell find -type f -name '*.c' -o -name '*.h' | grep -f ./tools/style.c.include | grep -v -f ./tools/style.c.exclude )

@ -1,13 +1,12 @@
#!/usr/bin/env python3
import json
import sys
from glob import glob
import json
from hashlib import sha256
try:
opt = sys.argv[1]
except:
except IndexError:
print("Usage: gen.py [core|mcu|check])")
sys.exit(1)
@ -22,12 +21,12 @@ def gen_core(data):
for d in data:
if "u2f" in d:
url, label = d["u2f"], d["label"]
print(" \"%s\": \"%s\"," % (url, label))
print(' "%s": "%s",' % (url, label))
print(" # WebAuthn")
for d in data:
if "webauthn" in d:
origin, label = d["webauthn"], d["label"]
print(" \"%s\": \"%s\"," % (origin, label))
print(' "%s": "%s",' % (origin, label))
print("}")
@ -36,12 +35,17 @@ def gen_mcu(data):
if "u2f" in d:
url, label = d["u2f"], d["label"]
h = sha256(url.encode()).digest()
print("\t{\n\t\t// U2F: %s\n\t\t%s,\n\t\t\"%s\"\n\t}," % (url, c_bytes(h), label))
print(
'\t{\n\t\t// U2F: %s\n\t\t%s,\n\t\t"%s"\n\t},'
% (url, c_bytes(h), label)
)
if "webauthn" in d:
origin, label = d["webauthn"], d["label"]
h = sha256(origin.encode()).digest()
print("\t{\n\t\t// WebAuthn: %s\n\t\t%s,\n\t\t\"%s\"\n\t}," % (origin, c_bytes(h), label))
print(
'\t{\n\t\t// WebAuthn: %s\n\t\t%s,\n\t\t"%s"\n\t},'
% (origin, c_bytes(h), label)
)
data = []

@ -1,3 +1,4 @@
// clang-format off
// TREZORv1 production public keys
"\x04\xd5\x71\xb7\xf1\x48\xc5\xe4\x23\x2c\x38\x14\xf7\x77\xd8\xfa\xea\xf1\xa8\x42\x16\xc7\x8d\x56\x9b\x71\x04\x1f\xfc\x76\x8a\x5b\x2d\x81\x0f\xc3\xbb\x13\x4d\xd0\x26\xb5\x7e\x65\x00\x52\x75\xae\xde\xf4\x3e\x15\x5f\x48\xfc\x11\xa3\x2e\xc7\x90\xa9\x33\x12\xbd\x58",
"\x04\x63\x27\x9c\x0c\x08\x66\xe5\x0c\x05\xc7\x99\xd3\x2b\xd6\xba\xb0\x18\x8b\x6d\xe0\x65\x36\xd1\x10\x9d\x2e\xd9\xce\x76\xcb\x33\x5c\x49\x0e\x55\xae\xe1\x0c\xc9\x01\x21\x51\x32\xe8\x53\x09\x7d\x54\x32\xed\xa0\x6b\x79\x20\x73\xbd\x77\x40\xc9\x4c\xe4\x51\x6c\xb1",

@ -1,2 +1,3 @@
// clang-format off
// sample public key "correct horse battery staple"
"\x04\x78\xd4\x30\x27\x4f\x8c\x5e\xc1\x32\x13\x38\x15\x1e\x9f\x27\xf4\xc6\x76\xa0\x08\xbd\xf8\x63\x8d\x07\xc0\xb6\xbe\x9a\xb3\x5c\x71\xa1\x51\x80\x63\x24\x3a\xcd\x4d\xfe\x96\xb6\x6e\x3f\x2e\xc8\x01\x3c\x8e\x07\x2c\xd0\x9b\x38\x34\xa1\x9f\x81\xf6\x59\xcc\x34\x55"

@ -1,8 +1,8 @@
#!/usr/bin/env python3
from glob import glob
import os
import re
import sys
from glob import glob
error = False
@ -21,7 +21,9 @@ for fn in sorted(glob(os.path.join(MYDIR, "messages-*.proto"))):
line = line.strip().split(" ")
if line[0] not in ["enum", "message"]:
continue
if not line[1].startswith(prefix) and not line[1].startswith("Debug" + prefix):
if not line[1].startswith(prefix) and not line[1].startswith(
"Debug" + prefix
):
print("ERROR:", fn, line[1])
error = True

@ -1,10 +1,10 @@
#!/usr/bin/env python3
from collections import defaultdict, OrderedDict
import re
import os
import json
import glob
import json
import logging
import os
import re
from collections import OrderedDict, defaultdict
try:
import requests

@ -3,38 +3,38 @@ from trezorlib import protobuf as p
class CoinDef(p.MessageType):
FIELDS = {
1: ('coin_name', p.UnicodeType, 0),
2: ('coin_shortcut', p.UnicodeType, 0),
3: ('coin_label', p.UnicodeType, 0),
4: ('curve_name', p.UnicodeType, 0),
5: ('address_type', p.UVarintType, 0),
6: ('address_type_p2sh', p.UVarintType, 0),
7: ('maxfee_kb', p.UVarintType, 0),
8: ('minfee_kb', p.UVarintType, 0),
9: ('signed_message_header', p.BytesType, 0),
10: ('hash_genesis_block', p.BytesType, 0),
11: ('xprv_magic', p.UVarintType, 0),
12: ('xpub_magic', p.UVarintType, 0),
13: ('xpub_magic_segwit_p2sh', p.UVarintType, 0),
14: ('xpub_magic_segwit_native', p.UVarintType, 0),
15: ('bech32_prefix', p.UnicodeType, 0),
16: ('cashaddr_prefix', p.UnicodeType, 0),
17: ('slip44', p.UVarintType, 0),
18: ('segwit', p.BoolType, 0),
19: ('decred', p.BoolType, 0),
20: ('fork_id', p.UVarintType, 0),
21: ('force_bip143', p.BoolType, 0),
22: ('dust_limit', p.UVarintType, 0),
23: ('uri_prefix', p.UnicodeType, 0),
24: ('min_address_length', p.UVarintType, 0),
25: ('max_address_length', p.UVarintType, 0),
26: ('icon', p.BytesType, 0),
28: ('website', p.UnicodeType, 0),
29: ('github', p.UnicodeType, 0),
30: ('maintainer', p.UnicodeType, 0),
31: ('blocktime_seconds', p.UVarintType, 0),
32: ('bip115', p.BoolType, 0),
33: ('cooldown', p.UVarintType, 0),
1: ("coin_name", p.UnicodeType, 0),
2: ("coin_shortcut", p.UnicodeType, 0),
3: ("coin_label", p.UnicodeType, 0),
4: ("curve_name", p.UnicodeType, 0),
5: ("address_type", p.UVarintType, 0),
6: ("address_type_p2sh", p.UVarintType, 0),
7: ("maxfee_kb", p.UVarintType, 0),
8: ("minfee_kb", p.UVarintType, 0),
9: ("signed_message_header", p.BytesType, 0),
10: ("hash_genesis_block", p.BytesType, 0),
11: ("xprv_magic", p.UVarintType, 0),
12: ("xpub_magic", p.UVarintType, 0),
13: ("xpub_magic_segwit_p2sh", p.UVarintType, 0),
14: ("xpub_magic_segwit_native", p.UVarintType, 0),
15: ("bech32_prefix", p.UnicodeType, 0),
16: ("cashaddr_prefix", p.UnicodeType, 0),
17: ("slip44", p.UVarintType, 0),
18: ("segwit", p.BoolType, 0),
19: ("decred", p.BoolType, 0),
20: ("fork_id", p.UVarintType, 0),
21: ("force_bip143", p.BoolType, 0),
22: ("dust_limit", p.UVarintType, 0),
23: ("uri_prefix", p.UnicodeType, 0),
24: ("min_address_length", p.UVarintType, 0),
25: ("max_address_length", p.UVarintType, 0),
26: ("icon", p.BytesType, 0),
28: ("website", p.UnicodeType, 0),
29: ("github", p.UnicodeType, 0),
30: ("maintainer", p.UnicodeType, 0),
31: ("blocktime_seconds", p.UVarintType, 0),
32: ("bip115", p.BoolType, 0),
33: ("cooldown", p.UVarintType, 0),
}
def __init__(
@ -73,7 +73,7 @@ class CoinDef(p.MessageType):
default_fee_b: dict = None,
bitcore: dict = None,
blockbook: dict = None,
cooldown: int = None
cooldown: int = None,
):
self.coin_name = coin_name
self.coin_shortcut = coin_shortcut

@ -1,14 +1,15 @@
#!/usr/bin/env python3
"""Fetch information about coins and tokens supported by Trezor and update it in coins_details.json."""
import os
import time
import json
import logging
import requests
import os
import sys
import coin_info
import time
import click
import requests
import coin_info
LOG = logging.getLogger(__name__)
@ -149,7 +150,7 @@ def summary(coins, api_key):
try:
ret = coinmarketcap_call("global-metrics/quotes/latest", api_key)
total_marketcap = int(ret["data"]["quote"]["USD"]["total_market_cap"])
except:
except Exception:
pass
return dict(

@ -1,13 +1,13 @@
#!/usr/bin/env python3
import fnmatch
import glob
import io
import json
import logging
import re
import sys
import os
import glob
import re
import struct
import sys
import zlib
from collections import defaultdict
from hashlib import sha256
@ -524,8 +524,7 @@ def cli(colors):
# fmt: off
@click.option("--backend/--no-backend", "-b", default=False, help="Check blockbook/bitcore responses")
@click.option("--icons/--no-icons", default=True, help="Check icon files")
@click.option("-d", "--show-duplicates", type=click.Choice(("all", "nontoken", "errors")),
default="errors", help="How much information about duplicate shortcuts should be shown.")
@click.option("-d", "--show-duplicates", type=click.Choice(("all", "nontoken", "errors")), default="errors", help="How much information about duplicate shortcuts should be shown.")
# fmt: on
def check(backend, icons, show_duplicates):
"""Validate coin definitions.

@ -1,13 +1,12 @@
#!/usr/bin/env python3
import click
import json
import os
import requests
import tempfile
import subprocess
import sys
import tempfile
import click
import requests
LIVE_URL = "https://trezor.io/static/json/coins_details.json"
COINS_DETAILS = os.path.join(

@ -1,11 +1,13 @@
#!/usr/bin/env python3
import re
import json
import os
import re
import subprocess
import sys
import click
import coin_info
import json
SUPPORT_INFO = coin_info.get_support_data()

@ -39,7 +39,7 @@ CFLAGS += -DGITREV=$(GITREV)
## help commands:
help: ## show this help
@awk -f help.awk $(MAKEFILE_LIST)
@awk -f ../tools/help.awk $(MAKEFILE_LIST)
## dependencies commands:
@ -71,27 +71,6 @@ test_emu_monero: ## run selected monero device tests from monero-agent
pylint: ## run pylint on application sources and tests
pylint -E $(shell find src tests -name *.py)
## style commands:
style_check: ## run code style check on application sources and tests
flake8 --version
isort --version | grep "VERSION"
black --version
flake8 $(shell find src -name *.py)
isort --check-only $(shell find src -name *.py ! -path 'src/trezor/messages/*')
black --check $(shell find src -name *.py ! -path 'src/trezor/messages/*')
style: ## apply code style on application sources and tests
isort $(shell find src -name *.py ! -path 'src/trezor/messages/*')
black $(shell find src -name *.py ! -path 'src/trezor/messages/*')
cstyle_check: ## run code style check on low-level C code
./tools/clang-format-check embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h}
cstyle: ## apply code style on low-level C code
clang-format -i embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h}
## code generation:
templates: ## render Mako templates (for lists of coins, tokens, etc.)

@ -241,6 +241,4 @@ void display_refresh(void) {
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD
}
const char *display_save(const char *prefix) {
return NULL;
}
const char *display_save(const char *prefix) { return NULL; }

@ -498,6 +498,4 @@ void display_refresh(void) {
}
}
const char *display_save(const char *prefix) {
return NULL;
}
const char *display_save(const char *prefix) { return NULL; }

@ -1,3 +1,5 @@
// clang-format off
/*
* This file is part of the MicroPython project, http://micropython.org/
*

@ -31,6 +31,6 @@ def get_type(wire_type):
for msg_name in dir(MessageType):
# Modules contain internal variables that may cause exception here.
# No Message begins with underscore so it's safe to skip those.
if (msg_name[0] == '_'):
if msg_name[0] == "_":
continue
type_to_name[getattr(MessageType, msg_name)] = msg_name

@ -1,2 +0,0 @@
---
BasedOnStyle: Google

@ -5,9 +5,7 @@ START_TEST(test_ed25519_cardano_sign_vectors) {
ed25519_secret_key secret_key_extension;
ed25519_signature signature;
static const char
*vectors[] =
{
static const char *vectors[] = {
"6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea5"
"3", // private key
"60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8"

@ -5,10 +5,11 @@ import hashlib
import os
import random
import curve25519
import ecdsa
import pytest
import curve25519
def bytes2num(s):
res = 0
@ -30,48 +31,48 @@ class Point:
points = [
Point(
"secp256k1",
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
),
Point(
"secp256k1",
0x1,
0x4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee,
0x4218F20AE6C646B363DB68605822FB14264CA8D2587FDD6FBC750D587E76A7EE,
),
Point(
"secp256k1",
0x2,
0x66fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e,
0x66FBE727B2BA09E09F5A98D70A5EFCE8424C5FA425BBDA1C511F860657B8535E,
),
Point(
"secp256k1",
0x1b,
0x1adcea1cf831b0ad1653e769d1a229091d0cc68d4b0328691b9caacc76e37c90,
0x1B,
0x1ADCEA1CF831B0AD1653E769D1A229091D0CC68D4B0328691B9CAACC76E37C90,
),
Point(
"nist256p1",
0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5,
0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296,
0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5,
),
Point(
"nist256p1",
0x0,
0x66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4,
0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4,
),
Point(
"nist256p1",
0x0,
0x99b7a386f1d07c29dbcc42a27b5f9449abe3d50de25178e8d7407a95e8b06c0b,
0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B,
),
Point(
"nist256p1",
0xaf8bbdfe8cdd5577acbf345b543d28cf402f4e94d3865b97ea0787f2d3aa5d22,
0x35802b8b376b995265918b078bc109c21a535176585c40f519aca52d6afc147c,
0xAF8BBDFE8CDD5577ACBF345B543D28CF402F4E94D3865B97EA0787F2D3AA5D22,
0x35802B8B376B995265918B078BC109C21A535176585C40F519ACA52D6AFC147C,
),
Point(
"nist256p1",
0x80000,
0x580610071f440f0dcc14a22e2d5d5afc1224c0cd11a3b4b51b8ecd2224ee1ce2,
0x580610071F440F0DCC14A22E2D5D5AFC1224C0CD11A3B4B51B8ECD2224EE1CE2,
),
]

@ -102,7 +102,7 @@ def is_valid_der(data):
try:
structure, _ = der_decode(data)
return data == der_encode(structure)
except:
except Exception:
return False
@ -140,7 +140,7 @@ def parse_ec_pubkey(public_key):
try:
public_key = bytes(public_key["public_key"].asOctets())
except:
except Exception:
raise ParseError("Not a BER encoded named elliptic curve public key")
return curve_name, public_key
@ -152,13 +152,13 @@ def parse_ecdsa256_signature(signature):
raise ParseError("Not a valid DER")
try:
signature, _ = der_decode(signature, asn1Spec=EcSignature())
except:
except Exception:
raise ParseError("Not a valid DER encoded ECDSA signature")
try:
r = int(signature["r"]).to_bytes(32, byteorder="big")
s = int(signature["s"]).to_bytes(32, byteorder="big")
signature = r + s
except:
except Exception:
raise ParseError("Not a valid DER encoded 256 bit ECDSA signature")
return signature
@ -281,7 +281,7 @@ def aes_cbc_decrypt(key, iv, ciphertext):
def load_json_testvectors(filename):
try:
result = json.loads(open(os.path.join(testvectors_directory, filename)).read())
except:
except Exception:
raise DataError()
return result
@ -310,7 +310,7 @@ def generate_aes(filename):
plaintext = unhexlify(test["msg"])
ciphertext = unhexlify(test["ct"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if len(key) not in [128 / 8, 192 / 8, 256 / 8]:
@ -359,7 +359,7 @@ def generate_chacha_poly(filename):
ciphertext = unhexlify(test["ct"])
tag = unhexlify(test["tag"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:
@ -406,7 +406,7 @@ def generate_curve25519_dh(filename):
private_key = unhexlify(test["private"])
shared = unhexlify(test["shared"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if curve_name != "curve25519":
@ -448,7 +448,7 @@ def generate_ecdh(filename):
private_key = parse_signed_hex(test["private"])
shared = unhexlify(test["shared"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
try:
@ -498,7 +498,7 @@ def generate_ecdsa(filename):
try:
public_key = unhexlify(test_group["keyDer"])
except:
except Exception:
raise DataError()
try:
@ -521,7 +521,7 @@ def generate_ecdsa(filename):
signature = unhexlify(test["sig"])
message = unhexlify(test["msg"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:
@ -563,7 +563,7 @@ def generate_eddsa(filename):
try:
public_key = unhexlify(test_group["keyDer"])
except:
except Exception:
raise DataError()
try:
@ -579,7 +579,7 @@ def generate_eddsa(filename):
signature = unhexlify(test["sig"])
message = unhexlify(test["msg"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:

@ -1,2 +0,0 @@
---
BasedOnStyle: Google

@ -1,12 +1,12 @@
#!/usr/bin/env python
from __future__ import print_function
bl = open('bl.bin').read()
fw = open('fw.bin').read()
combined = bl + fw[:256] + (32768-256)*'\x00' + fw[256:]
bl = open("bl.bin").read()
fw = open("fw.bin").read()
combined = bl + fw[:256] + (32768 - 256) * "\x00" + fw[256:]
open('combined.bin', 'w').write(combined)
open("combined.bin", "w").write(combined)
print('bootloader : %d bytes' % len(bl))
print('firmware : %d bytes' % len(fw))
print('combined : %d bytes' % len(combined))
print("bootloader : %d bytes" % len(bl))
print("firmware : %d bytes" % len(fw))
print("combined : %d bytes" % len(combined))

@ -1,6 +1,6 @@
#!/usr/bin/env python3
import sys
import os
import sys
TOTALSIZE = 32768
MAXSIZE = TOTALSIZE - 32
@ -8,7 +8,10 @@ MAXSIZE = TOTALSIZE - 32
fn = sys.argv[1]
fs = os.stat(fn).st_size
if fs > MAXSIZE:
raise Exception('bootloader has to be smaller than %d bytes (current size is %d)' % (MAXSIZE, fs))
with open(fn, 'ab') as f:
f.write(b'\x00' * (TOTALSIZE - fs))
raise Exception(
"bootloader has to be smaller than %d bytes (current size is %d)"
% (MAXSIZE, fs)
)
with open(fn, "ab") as f:
f.write(b"\x00" * (TOTALSIZE - fs))
f.close()

@ -7,7 +7,6 @@ import struct
import ecdsa
SLOTS = 3
pubkeys = {
@ -112,6 +111,7 @@ def check_size(data):
size = struct.unpack("<L", data[12:16])[0]
assert size == len(data) - 1024
def check_signatures(data):
# Analyses given firmware and prints out
# status of included signatures
@ -146,7 +146,7 @@ def check_signatures(data):
used.append(indexes[x])
print("Slot #%d signature: VALID" % (x + 1), signature.hex())
except:
except Exception:
print("Slot #%d signature: INVALID" % (x + 1), signature.hex())
@ -202,7 +202,7 @@ def sign(data, is_pem):
index = i
break
if index == None:
if index is None:
raise Exception("Unable to find private key index. Unknown private key?")
signature = key.sign_deterministic(to_sign, hashfunc=hashlib.sha256)

@ -2,29 +2,37 @@
import hashlib
import os
import subprocess
import ecdsa
from binascii import hexlify, unhexlify
print('master secret:', end='')
import ecdsa
print("master secret:", end="")
h = input()
if h:
h = unhexlify(h).encode('ascii')
h = unhexlify(h).encode("ascii")
else:
h = hashlib.sha256(os.urandom(1024)).digest()
print()
print('master secret:', hexlify(h))
print("master secret:", hexlify(h))
print()
for i in range(1, 6):
se = hashlib.sha256(h + chr(i).encode('ascii')).hexdigest()
print('seckey', i, ':', se)
sk = ecdsa.SigningKey.from_secret_exponent(secexp = int(se, 16), curve=ecdsa.curves.SECP256k1, hashfunc=hashlib.sha256)
print('pubkey', i, ':', (b'04' + hexlify(sk.get_verifying_key().to_string())).decode('ascii'))
print(sk.to_pem().decode('ascii'))
se = hashlib.sha256(h + chr(i).encode("ascii")).hexdigest()
print("seckey", i, ":", se)
sk = ecdsa.SigningKey.from_secret_exponent(
secexp=int(se, 16), curve=ecdsa.curves.SECP256k1, hashfunc=hashlib.sha256
)
print(
"pubkey",
i,
":",
(b"04" + hexlify(sk.get_verifying_key().to_string())).decode("ascii"),
)
print(sk.to_pem().decode("ascii"))
p = subprocess.Popen('ssss-split -t 3 -n 5 -x'.split(' '), stdin = subprocess.PIPE)
p.communicate(input = hexlify(h) + '\n')
p = subprocess.Popen("ssss-split -t 3 -n 5 -x".split(" "), stdin=subprocess.PIPE)
p.communicate(input=hexlify(h) + "\n")
# to recover use:
# $ ssss-combine -t 3 -x

@ -1,19 +1,19 @@
#!/usr/bin/env python
from hashlib import sha256
fn = '../bootloader/bootloader.bin'
fn = "../bootloader/bootloader.bin"
data = open(fn, 'rb').read()
data = open(fn, "rb").read()
if len(data) > 32768:
raise Exception('bootloader has to be smaller than 32768 bytes')
raise Exception("bootloader has to be smaller than 32768 bytes")
data += b'\x00' * (32768 - len(data))
data += b"\x00" * (32768 - len(data))
h = sha256(sha256(data).digest()).digest()
bl_hash = ', '.join('0x%02x' % x for x in bytearray(h))
bl_data = ', '.join('0x%02x' % x for x in bytearray(data))
bl_hash = ", ".join("0x%02x" % x for x in bytearray(h))
bl_data = ", ".join("0x%02x" % x for x in bytearray(data))
with open('bl_data.h', 'wt') as f:
f.write('static const uint8_t bl_hash[32] = {%s};\n' % bl_hash)
f.write('static const uint8_t bl_data[32768] = {%s};\n' % bl_data)
with open("bl_data.h", "wt") as f:
f.write("static const uint8_t bl_hash[32] = {%s};\n" % bl_hash)
f.write("static const uint8_t bl_data[32768] = {%s};\n" % bl_data)

@ -256,12 +256,12 @@ void fsm_msgEntropyAck(const EntropyAck *msg) {
}
void fsm_msgBackupDevice(const BackupDevice *msg) {
(void)msg;
CHECK_INITIALIZED
CHECK_PIN_UNCACHED
(void)
msg;
char mnemonic[MAX_MNEMONIC_LEN + 1];
if (config_getMnemonic(mnemonic, sizeof(mnemonic))) {
reset_backup(true, mnemonic);

@ -1,11 +1,16 @@
#!/usr/bin/env python
import sys
from collections import defaultdict
from messages_pb2 import MessageType
from messages_pb2 import wire_in, wire_out
from messages_pb2 import wire_debug_in, wire_debug_out
from messages_pb2 import wire_bootloader, wire_no_fsm
from messages_pb2 import (
MessageType,
wire_bootloader,
wire_debug_in,
wire_debug_out,
wire_in,
wire_no_fsm,
wire_out,
)
fh = open("messages_map.h", "wt")
fl = open("messages_map_limits.h", "wt")
@ -24,7 +29,7 @@ LABELS = {
def handle_message(fh, fl, skipped, message, extension):
name = message.name
short_name = name.split("MessageType_", 1).pop()
assert(short_name != name)
assert short_name != name
for s in skipped:
if short_name.startswith(s):
@ -37,14 +42,14 @@ def handle_message(fh, fl, skipped, message, extension):
bootloader = options.Extensions[wire_bootloader]
no_fsm = options.Extensions[wire_no_fsm]
if getattr(options, 'deprecated', None):
fh.write('\t// Message %s is deprecated\n' % short_name)
if getattr(options, "deprecated", None):
fh.write("\t// Message %s is deprecated\n" % short_name)
return
if bootloader:
fh.write('\t// Message %s is used in bootloader mode only\n' % short_name)
fh.write("\t// Message %s is used in bootloader mode only\n" % short_name)
return
if no_fsm:
fh.write('\t// Message %s is not used in FSM\n' % short_name)
fh.write("\t// Message %s is not used in FSM\n" % short_name)
return
if direction == "i":
@ -52,13 +57,15 @@ def handle_message(fh, fl, skipped, message, extension):
else:
process_func = "0"
fh.write(TEMPLATE.format(
fh.write(
TEMPLATE.format(
type="'%c'," % interface,
dir="'%c'," % direction,
msg_id="MessageType_%s," % name,
fields="%s_fields," % short_name,
process_func=process_func,
))
)
)
bufsize = None
t = interface + direction
@ -69,13 +76,20 @@ def handle_message(fh, fl, skipped, message, extension):
elif t == "do":
bufsize = "MSG_DEBUG_OUT_SIZE"
if bufsize:
fl.write("_Static_assert(%s >= sizeof(%s), \"msg buffer too small\");\n" % (bufsize, short_name))
fl.write(
'_Static_assert(%s >= sizeof(%s), "msg buffer too small");\n'
% (bufsize, short_name)
)
skipped = sys.argv[1:]
fh.write("\t// This file is automatically generated by messages_map.py -- DO NOT EDIT!\n")
fl.write("// This file is automatically generated by messages_map.py -- DO NOT EDIT!\n\n")
fh.write(
"\t// This file is automatically generated by messages_map.py -- DO NOT EDIT!\n"
)
fl.write(
"// This file is automatically generated by messages_map.py -- DO NOT EDIT!\n\n"
)
messages = defaultdict(list)

@ -1,3 +1,4 @@
// clang-format off
/**
* Copyright FIDO Alliance, 2017
*

@ -1,3 +1,4 @@
// clang-format off
/**
* Copyright FIDO Alliance, 2017
*

@ -1,3 +1,4 @@
// clang-format off
#include "bitmaps.h"
const uint8_t bmp_digit0_data[] = { 0xff, 0xff, 0xf8, 0x1f, 0xf0, 0x0f, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xe1, 0x87, 0xf0, 0x0f, 0xf8, 0x1f, 0xff, 0xff, };

@ -1,45 +1,50 @@
#!/usr/bin/env python3
import glob
import os
from PIL import Image
hdrs = []
data = []
imgs = []
def encode_pixels(img):
r = ''
img = [ (x[0] + x[1] + x[2] > 384 and '1' or '0') for x in img]
r = ""
img = [(x[0] + x[1] + x[2] > 384 and "1" or "0") for x in img]
for i in range(len(img) // 8):
c = ''.join(img[i * 8 : i * 8 + 8])
r += '0x%02x, ' % int(c, 2)
c = "".join(img[i * 8 : i * 8 + 8])
r += "0x%02x, " % int(c, 2)
return r
cnt = 0
for fn in sorted(glob.glob('*.png')):
print('Processing:', fn)
for fn in sorted(glob.glob("*.png")):
print("Processing:", fn)
im = Image.open(fn)
name = os.path.splitext(fn)[0]
w, h = im.size
if w % 8 != 0:
raise Exception('Width must be divisable by 8! (%s is %dx%d)' % (fn, w, h))
raise Exception("Width must be divisable by 8! (%s is %dx%d)" % (fn, w, h))
img = list(im.getdata())
hdrs.append('extern const BITMAP bmp_%s;\n' % name)
imgs.append('const BITMAP bmp_%s = {%d, %d, bmp_%s_data};\n' % (name, w, h, name))
data.append('const uint8_t bmp_%s_data[] = { %s};\n' % (name, encode_pixels(img)))
hdrs.append("extern const BITMAP bmp_%s;\n" % name)
imgs.append("const BITMAP bmp_%s = {%d, %d, bmp_%s_data};\n" % (name, w, h, name))
data.append("const uint8_t bmp_%s_data[] = { %s};\n" % (name, encode_pixels(img)))
cnt += 1
with open('../bitmaps.c', 'wt') as f:
with open("../bitmaps.c", "wt") as f:
f.write("// clang-format off\n")
f.write('#include "bitmaps.h"\n\n')
for i in range(cnt):
f.write(data[i])
f.write('\n')
f.write("\n")
for i in range(cnt):
f.write(imgs[i])
f.close()
with open('../bitmaps.h', 'wt') as f:
f.write('''#ifndef __BITMAPS_H__
with open("../bitmaps.h", "wt") as f:
f.write(
"""#ifndef __BITMAPS_H__
#define __BITMAPS_H__
#include <stdint.h>
@ -49,10 +54,11 @@ typedef struct {
const uint8_t *data;
} BITMAP;
''')
"""
)
for i in range(cnt):
f.write(hdrs[i])
f.write('\n#endif\n')
f.write("\n#endif\n")
f.close()

@ -9,9 +9,7 @@ const uint8_t * const font_data[2][128] = {
},
};
int fontCharWidth(int font, char c) {
return font_data[font][c & 0x7f][0];
}
int fontCharWidth(int font, char c) { return font_data[font][c & 0x7f][0]; }
const uint8_t *fontCharData(int font, char c) {
return font_data[font][c & 0x7f] + 1;

@ -1,8 +1,8 @@
#!/usr/bin/env python3
from PIL import Image
class Img(object):
class Img(object):
def __init__(self, fn):
im = Image.open(fn)
self.w, self.h = im.size
@ -11,29 +11,30 @@ class Img(object):
def pixel(self, r, c):
p = self.data[r + c * self.w]
if p == (255, 255, 255):
return '0'
return "0"
if p == (0, 0, 0):
return '1'
return "1"
if p == (255, 0, 255):
return None
raise Exception('Unknown color', p)
raise Exception("Unknown color", p)
def convert(imgfile, outfile):
img = Img(imgfile)
cur = ''
with open(outfile, 'w') as f:
cur = ""
with open(outfile, "w") as f:
for i in range(128):
x = (i % 16) * 10
y = (i // 16) * 10
cur = ''
while img.pixel(x, y) != None:
val = ''.join(img.pixel(x, y + j) for j in range(8))
cur = ""
while img.pixel(x, y) is not None:
val = "".join(img.pixel(x, y + j) for j in range(8))
x += 1
cur += '\\x%02x' % int(val, 2)
cur = '\\x%02x' % (len(cur) // 4) + cur
ch = chr(i) if i >= 32 and i <= 126 else '_'
cur += "\\x%02x" % int(val, 2)
cur = "\\x%02x" % (len(cur) // 4) + cur
ch = chr(i) if i >= 32 and i <= 126 else "_"
f.write('\t/* 0x%02x %c */ (uint8_t *)"%s",\n' % (i, ch, cur))
convert('fonts/fontfixed.png', 'fontfixed.inc')
convert('fonts/font.png', 'font.inc')
convert("fonts/fontfixed.png", "fontfixed.inc")
convert("fonts/font.png", "font.inc")

@ -2,99 +2,102 @@
from __future__ import print_function
handlers = [
'hard_fault_handler',
'mem_manage_handler',
'bus_fault_handler',
'usage_fault_handler',
'nvic_wwdg_isr',
'pvd_isr',
'tamp_stamp_isr',
'rtc_wkup_isr',
'flash_isr',
'rcc_isr',
'exti0_isr',
'exti1_isr',
'exti2_isr',
'exti3_isr',
'exti4_isr',
'dma1_stream0_isr',
'dma1_stream1_isr',
'dma1_stream2_isr',
'dma1_stream3_isr',
'dma1_stream4_isr',
'dma1_stream5_isr',
'dma1_stream6_isr',
'adc_isr',
'can1_tx_isr',
'can1_rx0_isr',
'can1_rx1_isr',
'can1_sce_isr',
'exti9_5_isr',
'tim1_brk_tim9_isr',
'tim1_up_tim10_isr',
'tim1_trg_com_tim11_isr',
'tim1_cc_isr',
'tim2_isr',
'tim3_isr',
'tim4_isr',
'i2c1_ev_isr',
'i2c1_er_isr',
'i2c2_ev_isr',
'i2c2_er_isr',
'spi1_isr',
'spi2_isr',
'usart1_isr',
'usart2_isr',
'usart3_isr',
'exti15_10_isr',
'rtc_alarm_isr',
'usb_fs_wkup_isr',
'tim8_brk_tim12_isr',
'tim8_up_tim13_isr',
'tim8_trg_com_tim14_isr',
'tim8_cc_isr',
'dma1_stream7_isr',
'fsmc_isr',
'sdio_isr',
'tim5_isr',
'spi3_isr',
'uart4_isr',
'uart5_isr',
'tim6_dac_isr',
'tim7_isr',
'dma2_stream0_isr',
'dma2_stream1_isr',
'dma2_stream2_isr',
'dma2_stream3_isr',
'dma2_stream4_isr',
'eth_isr',
'eth_wkup_isr',
'can2_tx_isr',
'can2_rx0_isr',
'can2_rx1_isr',
'can2_sce_isr',
'otg_fs_isr',
'dma2_stream5_isr',
'dma2_stream6_isr',
'dma2_stream7_isr',
'usart6_isr',
'i2c3_ev_isr',
'i2c3_er_isr',
'otg_hs_ep1_out_isr',
'otg_hs_ep1_in_isr',
'otg_hs_wkup_isr',
'otg_hs_isr',
'dcmi_isr',
'cryp_isr',
'hash_rng_isr',
"hard_fault_handler",
"mem_manage_handler",
"bus_fault_handler",
"usage_fault_handler",
"nvic_wwdg_isr",
"pvd_isr",
"tamp_stamp_isr",
"rtc_wkup_isr",
"flash_isr",
"rcc_isr",
"exti0_isr",
"exti1_isr",
"exti2_isr",
"exti3_isr",
"exti4_isr",
"dma1_stream0_isr",
"dma1_stream1_isr",
"dma1_stream2_isr",
"dma1_stream3_isr",
"dma1_stream4_isr",
"dma1_stream5_isr",
"dma1_stream6_isr",
"adc_isr",
"can1_tx_isr",
"can1_rx0_isr",
"can1_rx1_isr",
"can1_sce_isr",
"exti9_5_isr",
"tim1_brk_tim9_isr",
"tim1_up_tim10_isr",
"tim1_trg_com_tim11_isr",
"tim1_cc_isr",
"tim2_isr",
"tim3_isr",
"tim4_isr",
"i2c1_ev_isr",
"i2c1_er_isr",
"i2c2_ev_isr",
"i2c2_er_isr",
"spi1_isr",
"spi2_isr",
"usart1_isr",
"usart2_isr",
"usart3_isr",
"exti15_10_isr",
"rtc_alarm_isr",
"usb_fs_wkup_isr",
"tim8_brk_tim12_isr",
"tim8_up_tim13_isr",
"tim8_trg_com_tim14_isr",
"tim8_cc_isr",
"dma1_stream7_isr",
"fsmc_isr",
"sdio_isr",
"tim5_isr",
"spi3_isr",
"uart4_isr",
"uart5_isr",
"tim6_dac_isr",
"tim7_isr",
"dma2_stream0_isr",
"dma2_stream1_isr",
"dma2_stream2_isr",
"dma2_stream3_isr",
"dma2_stream4_isr",
"eth_isr",
"eth_wkup_isr",
"can2_tx_isr",
"can2_rx0_isr",
"can2_rx1_isr",
"can2_sce_isr",
"otg_fs_isr",
"dma2_stream5_isr",
"dma2_stream6_isr",
"dma2_stream7_isr",
"usart6_isr",
"i2c3_ev_isr",
"i2c3_er_isr",
"otg_hs_ep1_out_isr",
"otg_hs_ep1_in_isr",
"otg_hs_wkup_isr",
"otg_hs_isr",
"dcmi_isr",
"cryp_isr",
"hash_rng_isr",
]
with open('handlers.c', 'wt') as f:
with open("handlers.c", "wt") as f:
f.write('#include "layout.h"\n')
f.write('#include "oled.h"\n\n')
for i in handlers:
f.write('void __attribute__((noreturn)) %s(void)\n' % i)
f.write('{\n')
f.write('\tlayoutDialog(DIALOG_ICON_ERROR, NULL, NULL, NULL, "Encountered", NULL, "%s", NULL, "Please restart", "the device.");\n' % i.upper())
f.write('\tfor (;;) {} // loop forever\n')
f.write('}\n\n')
f.write("void __attribute__((noreturn)) %s(void)\n" % i)
f.write("{\n")
f.write(
'\tlayoutDialog(DIALOG_ICON_ERROR, NULL, NULL, NULL, "Encountered", NULL, "%s", NULL, "Please restart", "the device.");\n'
% i.upper()
)
f.write("\tfor (;;) {} // loop forever\n")
f.write("}\n\n")

@ -1,7 +1,7 @@
#include <readline/history.h>
#include <readline/readline.h>
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "fonts.h"

@ -0,0 +1,35 @@
[flake8]
ignore =
# E203 whitespace before ':'
E203,
# E221: multiple spaces before operator
E221,
# E241: multiple spaces after ':'
E241,
# E402: module level import not at top of file
E402,
# E501: line too long
E501,
# E741 ambiguous variable name
E741,
# F403: star import used, unable to detect undefined names
F403,
# F405: name may be undefined, or defined from star imports
F405,
# W503: line break before binary operator
W503
[isort]
multi_line_output = 3
include_trailing_comma = True
force_grid_wrap = 0
combine_as_imports = True
line_length = 88
not_skip=__init__.py
forced_separate = apps
known_standard_library = micropython,ubinascii,ustruct,uctypes,utime,utimeq,trezorio,trezorui,trezorutils,trezorconfig
[tool:pytest]
addopts = --pyargs trezorlib.tests.device_tests
xfail_strict = true
run_xfail =

@ -19,9 +19,9 @@
#include <string.h>
#include "norcow.h"
#include "flash.h"
#include "common.h"
#include "flash.h"
#include "norcow.h"
// NRC2 = 4e524332
#define NORCOW_MAGIC ((uint32_t)0x3243524e)
@ -40,12 +40,14 @@
#define NORCOW_KEY_DELETED (0x0000)
// The offset from the beginning of the sector where stored items start.
#define NORCOW_STORAGE_START (NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN)
#define NORCOW_STORAGE_START \
(NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN)
// Map from sector index to sector number.
static const uint8_t norcow_sectors[NORCOW_SECTOR_COUNT] = NORCOW_SECTORS;
// The index of the active reading sector and writing sector. These should be equal except when storage version upgrade or compaction is in progress.
// The index of the active reading sector and writing sector. These should be
// equal except when storage version upgrade or compaction is in progress.
static uint8_t norcow_active_sector = 0;
static uint8_t norcow_write_sector = 0;
@ -59,8 +61,7 @@ static uint32_t norcow_free_offset = 0;
* Returns pointer to sector, starting with offset
* Fails when there is not enough space for data of given size
*/
static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size)
{
static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size) {
ensure(sectrue * (sector <= NORCOW_SECTOR_COUNT), "invalid sector");
return flash_get_address(norcow_sectors[sector], offset, size);
}
@ -68,8 +69,8 @@ static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size)
/*
* Writes data to given sector, starting from offset
*/
static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix, const uint8_t *data, uint16_t len)
{
static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
const uint8_t *data, uint16_t len) {
if (sector >= NORCOW_SECTOR_COUNT) {
return secfalse;
}
@ -105,8 +106,7 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix, co
/*
* Erases sector (and sets a magic)
*/
static void erase_sector(uint8_t sector, secbool set_magic)
{
static void erase_sector(uint8_t sector, secbool set_magic) {
#if NORCOW_HEADER_LEN > 0
// Backup the sector header.
uint32_t header_backup[NORCOW_HEADER_LEN / sizeof(uint32_t)];
@ -120,14 +120,19 @@ static void erase_sector(uint8_t sector, secbool set_magic)
// Copy the sector header back.
ensure(flash_unlock_write(), NULL);
for (uint32_t i = 0; i < NORCOW_HEADER_LEN / sizeof(uint32_t); ++i) {
ensure(flash_write_word(norcow_sectors[sector], i*sizeof(uint32_t), header_backup[i]), NULL);
ensure(flash_write_word(norcow_sectors[sector], i * sizeof(uint32_t),
header_backup[i]),
NULL);
}
ensure(flash_lock_write(), NULL);
#endif
if (sectrue == set_magic) {
ensure(norcow_write(sector, NORCOW_HEADER_LEN, NORCOW_MAGIC, NULL, 0), "set magic failed");
ensure(norcow_write(sector, NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN, ~NORCOW_VERSION, NULL, 0), "set version failed");
ensure(norcow_write(sector, NORCOW_HEADER_LEN, NORCOW_MAGIC, NULL, 0),
"set magic failed");
ensure(norcow_write(sector, NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN,
~NORCOW_VERSION, NULL, 0),
"set version failed");
}
}
@ -136,8 +141,8 @@ static void erase_sector(uint8_t sector, secbool set_magic)
/*
* Reads one item starting from offset
*/
static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key, const void **val, uint16_t *len, uint32_t *pos)
{
static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key,
const void **val, uint16_t *len, uint32_t *pos) {
*pos = offset;
const void *k = norcow_ptr(sector, *pos, 2);
@ -163,8 +168,8 @@ static secbool read_item(uint8_t sector, uint32_t offset, uint16_t *key, const v
/*
* Writes one item starting from offset
*/
static secbool write_item(uint8_t sector, uint32_t offset, uint16_t key, const void *val, uint16_t len, uint32_t *pos)
{
static secbool write_item(uint8_t sector, uint32_t offset, uint16_t key,
const void *val, uint16_t len, uint32_t *pos) {
uint32_t prefix = ((uint32_t)len << 16) | key;
*pos = offset + NORCOW_PREFIX_LEN + len;
ALIGN4(*pos);
@ -174,9 +179,10 @@ static secbool write_item(uint8_t sector, uint32_t offset, uint16_t key, const v
/*
* Finds the offset from the beginning of the sector where stored items start.
*/
static secbool find_start_offset(uint8_t sector, uint32_t *offset, uint32_t *version)
{
const uint32_t *magic = norcow_ptr(sector, NORCOW_HEADER_LEN, NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN);
static secbool find_start_offset(uint8_t sector, uint32_t *offset,
uint32_t *version) {
const uint32_t *magic = norcow_ptr(sector, NORCOW_HEADER_LEN,
NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN);
if (magic == NULL) {
return secfalse;
}
@ -197,8 +203,8 @@ static secbool find_start_offset(uint8_t sector, uint32_t *offset, uint32_t *ver
/*
* Finds item in given sector
*/
static secbool find_item(uint8_t sector, uint16_t key, const void **val, uint16_t *len)
{
static secbool find_item(uint8_t sector, uint16_t key, const void **val,
uint16_t *len) {
*val = NULL;
*len = 0;
@ -227,8 +233,7 @@ static secbool find_item(uint8_t sector, uint16_t key, const void **val, uint16_
/*
* Finds first unused offset in given sector
*/
static uint32_t find_free_offset(uint8_t sector)
{
static uint32_t find_free_offset(uint8_t sector) {
uint32_t offset;
uint32_t version;
if (sectrue != find_start_offset(sector, &offset, &version)) {
@ -250,8 +255,7 @@ static uint32_t find_free_offset(uint8_t sector)
/*
* Compacts active sector and sets new active sector
*/
static void compact(void)
{
static void compact(void) {
uint32_t offsetr;
uint32_t version;
if (sectrue != find_start_offset(norcow_active_sector, &offsetr, &version)) {
@ -280,7 +284,8 @@ static void compact(void)
// copy the item
uint32_t posw;
ensure(write_item(norcow_write_sector, offsetw, k, v, l, &posw), "compaction write failed");
ensure(write_item(norcow_write_sector, offsetw, k, v, l, &posw),
"compaction write failed");
offsetw = posw;
}
@ -293,15 +298,15 @@ static void compact(void)
/*
* Initializes storage
*/
void norcow_init(uint32_t *norcow_version)
{
void norcow_init(uint32_t *norcow_version) {
flash_init();
secbool found = secfalse;
*norcow_version = 0;
// detect active sector - starts with magic and has highest version
for (uint8_t i = 0; i < NORCOW_SECTOR_COUNT; i++) {
uint32_t offset;
if (sectrue == find_start_offset(i, &offset, &norcow_active_version) && norcow_active_version >= *norcow_version) {
if (sectrue == find_start_offset(i, &offset, &norcow_active_version) &&
norcow_active_version >= *norcow_version) {
found = sectrue;
norcow_active_sector = i;
*norcow_version = norcow_active_version;
@ -326,8 +331,7 @@ void norcow_init(uint32_t *norcow_version)
/*
* Wipe the storage
*/
void norcow_wipe(void)
{
void norcow_wipe(void) {
erase_sector(0, sectrue);
for (uint8_t i = 1; i < NORCOW_SECTOR_COUNT; i++) {
erase_sector(i, secfalse);
@ -341,16 +345,16 @@ void norcow_wipe(void)
/*
* Looks for the given key, returns status of the operation
*/
secbool norcow_get(uint16_t key, const void **val, uint16_t *len)
{
secbool norcow_get(uint16_t key, const void **val, uint16_t *len) {
return find_item(norcow_active_sector, key, val, len);
}
/*
* Reads the next entry in the storage starting at offset. Returns secfalse if there is none.
* Reads the next entry in the storage starting at offset. Returns secfalse if
* there is none.
*/
secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val, uint16_t *len)
{
secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val,
uint16_t *len) {
if (*offset == 0) {
uint32_t version;
if (sectrue != find_start_offset(norcow_active_sector, offset, &version)) {
@ -400,14 +404,13 @@ secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val, uint1
* as val, then norcow_set allocates a new key of size len. The value should
* then be written using norcow_update_bytes().
*/
secbool norcow_set(uint16_t key, const void *val, uint16_t len)
{
secbool norcow_set(uint16_t key, const void *val, uint16_t len) {
secbool found;
return norcow_set_ex(key, val, len, &found);
}
secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *found)
{
secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
secbool *found) {
// Key 0xffff is used as a marker to indicate that the entry is not set.
if (key == NORCOW_KEY_FREE) {
return secfalse;
@ -422,12 +425,15 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *foun
// Try to update the entry if it already exists.
uint32_t offset = 0;
if (sectrue == *found) {
offset = (const uint8_t*) ptr - (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE);
offset =
(const uint8_t *)ptr -
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE);
if (val != NULL && len_old == len) {
ret = sectrue;
ensure(flash_unlock_write(), NULL);
for (uint16_t i = 0; i < len; i++) {
if (sectrue != flash_write_byte(sector_num, offset + i, ((const uint8_t*)val)[i])) {
if (sectrue != flash_write_byte(sector_num, offset + i,
((const uint8_t *)val)[i])) {
ret = secfalse;
break;
}
@ -444,7 +450,8 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *foun
// Update the prefix to indicate that the old item has been deleted.
uint32_t prefix = (uint32_t)len_old << 16;
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix), NULL);
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix),
NULL);
// Delete the old item data.
uint32_t end = offset + len_old;
@ -461,7 +468,8 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *foun
}
// Write new item.
uint32_t pos;
ret = write_item(norcow_write_sector, norcow_free_offset, key, val, len, &pos);
ret = write_item(norcow_write_sector, norcow_free_offset, key, val, len,
&pos);
if (sectrue == ret) {
norcow_free_offset = pos;
}
@ -472,8 +480,7 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *foun
/*
* Deletes the given key, returns status of the operation.
*/
secbool norcow_delete(uint16_t key)
{
secbool norcow_delete(uint16_t key) {
// Key 0xffff is used as a marker to indicate that the entry is not set.
if (key == NORCOW_KEY_FREE) {
return secfalse;
@ -486,13 +493,16 @@ secbool norcow_delete(uint16_t key)
return secfalse;
}
uint32_t offset = (const uint8_t*) ptr - (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE);
uint32_t offset =
(const uint8_t *)ptr -
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE);
ensure(flash_unlock_write(), NULL);
// Update the prefix to indicate that the item has been deleted.
uint32_t prefix = (uint32_t)len << 16;
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix), NULL);
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix),
NULL);
// Delete the item data.
uint32_t end = offset + len;
@ -510,8 +520,7 @@ secbool norcow_delete(uint16_t key)
* Update a word in flash at the given pointer. The pointer must point
* into the NORCOW area.
*/
secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value)
{
secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value) {
const void *ptr;
uint16_t len;
if (sectrue != find_item(norcow_write_sector, key, &ptr, &len)) {
@ -520,9 +529,14 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value)
if ((offset & 3) != 0 || offset >= len) {
return secfalse;
}
uint32_t sector_offset = (const uint8_t*) ptr - (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) + offset;
uint32_t sector_offset =
(const uint8_t *)ptr -
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) +
offset;
ensure(flash_unlock_write(), NULL);
ensure(flash_write_word(norcow_sectors[norcow_write_sector], sector_offset, value), NULL);
ensure(flash_write_word(norcow_sectors[norcow_write_sector], sector_offset,
value),
NULL);
ensure(flash_lock_write(), NULL);
return sectrue;
}
@ -530,8 +544,8 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value)
/*
* Update the value of the given key starting at the given offset.
*/
secbool norcow_update_bytes(const uint16_t key, const uint16_t offset, const uint8_t *data, const uint16_t len)
{
secbool norcow_update_bytes(const uint16_t key, const uint16_t offset,
const uint8_t *data, const uint16_t len) {
const void *ptr;
uint16_t allocated_len;
if (sectrue != find_item(norcow_write_sector, key, &ptr, &allocated_len)) {
@ -540,7 +554,10 @@ secbool norcow_update_bytes(const uint16_t key, const uint16_t offset, const uin
if (offset + len > allocated_len) {
return secfalse;
}
uint32_t sector_offset = (const uint8_t*) ptr - (const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) + offset;
uint32_t sector_offset =
(const uint8_t *)ptr -
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) +
offset;
uint8_t sector = norcow_sectors[norcow_write_sector];
ensure(flash_unlock_write(), NULL);
for (uint16_t i = 0; i < len; i++, sector_offset++) {
@ -553,8 +570,7 @@ secbool norcow_update_bytes(const uint16_t key, const uint16_t offset, const uin
/*
* Complete storage version upgrade
*/
secbool norcow_upgrade_finish(void)
{
secbool norcow_upgrade_finish(void) {
erase_sector(norcow_active_sector, secfalse);
norcow_active_sector = norcow_write_sector;
norcow_active_version = NORCOW_VERSION;

@ -45,9 +45,11 @@ void norcow_wipe(void);
secbool norcow_get(uint16_t key, const void **val, uint16_t *len);
/*
* Reads the next entry in the storage starting at offset. Returns secfalse if there is none.
* Reads the next entry in the storage starting at offset. Returns secfalse if
* there is none.
*/
secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val, uint16_t *len);
secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val,
uint16_t *len);
/*
* Sets the given key, returns status of the operation. If NULL is passed
@ -55,7 +57,8 @@ secbool norcow_get_next(uint32_t *offset, uint16_t *key, const void **val, uint1
* then be written using norcow_update_bytes().
*/
secbool norcow_set(uint16_t key, const void *val, uint16_t len);
secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len, secbool *found);
secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
secbool *found);
/*
* Deletes the given key, returns status of the operation.
@ -72,7 +75,8 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value);
* Update the value of the given key starting at the given offset.
* Note that you can only change bits from 1 to 0.
*/
secbool norcow_update_bytes(const uint16_t key, const uint16_t offset, const uint8_t *data, const uint16_t len);
secbool norcow_update_bytes(const uint16_t key, const uint16_t offset,
const uint8_t *data, const uint16_t len);
/*
* Complete storage version upgrade

@ -19,15 +19,15 @@
#include <string.h>
#include "chacha20poly1305/rfc7539.h"
#include "common.h"
#include "hmac.h"
#include "memzero.h"
#include "norcow.h"
#include "storage.h"
#include "pbkdf2.h"
#include "sha2.h"
#include "hmac.h"
#include "rand.h"
#include "memzero.h"
#include "chacha20poly1305/rfc7539.h"
#include "sha2.h"
#include "storage.h"
#define LOW_MASK 0x55555555
@ -37,7 +37,8 @@
// Norcow storage key of the PIN entry log and PIN success log.
#define PIN_LOGS_KEY ((APP_STORAGE << 8) | 0x01)
// Norcow storage key of the combined salt, EDEK, ESAK and PIN verification code entry.
// Norcow storage key of the combined salt, EDEK, ESAK and PIN verification code
// entry.
#define EDEK_PVC_KEY ((APP_STORAGE << 8) | 0x02)
// Norcow storage key of the PIN set flag.
@ -53,7 +54,8 @@
#define PIN_EMPTY 1
// Maximum number of failed unlock attempts.
// NOTE: The PIN counter logic relies on this constant being less than or equal to 16.
// NOTE: The PIN counter logic relies on this constant being less than or equal
// to 16.
#define PIN_MAX_TRIES 16
// The total number of iterations to use in PBKDF2.
@ -90,7 +92,8 @@
// The length of the storage authentication key in bytes.
#define SAK_SIZE 16
// The combined length of the data encryption key and the storage authentication key in bytes.
// The combined length of the data encryption key and the storage authentication
// key in bytes.
#define KEYS_SIZE (DEK_SIZE + SAK_SIZE)
// The length of the PIN verification code in bytes.
@ -134,12 +137,15 @@ static uint32_t norcow_active_version = 0;
static const uint8_t TRUE_BYTE = 0x01;
static const uint8_t FALSE_BYTE = 0x00;
static void __handle_fault(const char *msg, const char *file, int line, const char *func);
static void __handle_fault(const char *msg, const char *file, int line,
const char *func);
#define handle_fault(msg) (__handle_fault(msg, __FILE__, __LINE__, __func__))
static secbool storage_upgrade(void);
static secbool storage_set_encrypted(const uint16_t key, const void *val, const uint16_t len);
static secbool storage_get_encrypted(const uint16_t key, void *val_dest, const uint16_t max_len, uint16_t *len);
static secbool storage_set_encrypted(const uint16_t key, const void *val,
const uint16_t len);
static secbool storage_get_encrypted(const uint16_t key, void *val_dest,
const uint16_t max_len, uint16_t *len);
static secbool secequal(const void *ptr1, const void *ptr2, size_t n) {
const uint8_t *p1 = ptr1;
@ -160,7 +166,8 @@ static secbool secequal(const void* ptr1, const void* ptr2, size_t n) {
return diff ? secfalse : sectrue;
}
static secbool secequal32(const uint32_t* ptr1, const uint32_t* ptr2, size_t n) {
static secbool secequal32(const uint32_t *ptr1, const uint32_t *ptr2,
size_t n) {
uint32_t diff = 0;
size_t i;
for (i = 0; i < n; ++i) {
@ -189,7 +196,8 @@ static secbool is_protected(uint16_t key) {
static secbool auth_init(void) {
uint8_t tag[SHA256_DIGEST_LENGTH];
memzero(authentication_sum, sizeof(authentication_sum));
hmac_sha256(cached_sak, SAK_SIZE, authentication_sum, sizeof(authentication_sum), tag);
hmac_sha256(cached_sak, SAK_SIZE, authentication_sum,
sizeof(authentication_sum), tag);
return norcow_set(STORAGE_TAG_KEY, tag, STORAGE_TAG_SIZE);
}
@ -206,12 +214,14 @@ static secbool auth_update(uint16_t key) {
for (uint32_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
authentication_sum[i] ^= tag[i];
}
hmac_sha256(cached_sak, SAK_SIZE, authentication_sum, sizeof(authentication_sum), tag);
hmac_sha256(cached_sak, SAK_SIZE, authentication_sum,
sizeof(authentication_sum), tag);
return norcow_set(STORAGE_TAG_KEY, tag, STORAGE_TAG_SIZE);
}
/*
* A secure version of norcow_set(), which updates the storage authentication tag.
* A secure version of norcow_set(), which updates the storage authentication
* tag.
*/
static secbool auth_set(uint16_t key, const void *val, uint16_t len) {
secbool found;
@ -226,10 +236,10 @@ static secbool auth_set(uint16_t key, const void *val, uint16_t len) {
}
/*
* A secure version of norcow_get(), which checks the storage authentication tag.
* A secure version of norcow_get(), which checks the storage authentication
* tag.
*/
static secbool auth_get(uint16_t key, const void **val, uint16_t *len)
{
static secbool auth_get(uint16_t key, const void **val, uint16_t *len) {
*val = NULL;
*len = 0;
uint32_t sum[SHA256_DIGEST_LENGTH / sizeof(uint32_t)] = {0};
@ -269,7 +279,8 @@ static secbool auth_get(uint16_t key, const void **val, uint16_t *len)
}
continue;
}
g[0] = (((uint32_t)k & 0xff) << 24) | (((uint32_t)k & 0xff00) << 8) | 0x8000; // Add SHA message padding.
g[0] = (((uint32_t)k & 0xff) << 24) | (((uint32_t)k & 0xff00) << 8) |
0x8000; // Add SHA message padding.
sha256_Transform(idig, g, h);
sha256_Transform(odig, h, h);
for (uint32_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++) {
@ -304,7 +315,8 @@ static secbool auth_get(uint16_t key, const void **val, uint16_t *len)
REVERSE32(h[i], h[i]);
}
#endif
if (tag_val == NULL || tag_len != STORAGE_TAG_SIZE || sectrue != secequal(h, tag_val, STORAGE_TAG_SIZE)) {
if (tag_val == NULL || tag_len != STORAGE_TAG_SIZE ||
sectrue != secequal(h, tag_val, STORAGE_TAG_SIZE)) {
handle_fault("storage tag check");
}
@ -319,10 +331,10 @@ static secbool auth_get(uint16_t key, const void **val, uint16_t *len)
}
/*
* Generates a delay of random length. Use this to protect sensitive code against fault injection.
* Generates a delay of random length. Use this to protect sensitive code
* against fault injection.
*/
static void wait_random(void)
{
static void wait_random(void) {
#ifndef TREZOR_STORAGE_TEST
int wait = random32() & 0xff;
volatile int i = 0;
@ -342,8 +354,9 @@ static void wait_random(void)
#endif
}
static void derive_kek(uint32_t pin, const uint8_t *random_salt, uint8_t kek[SHA256_DIGEST_LENGTH], uint8_t keiv[SHA256_DIGEST_LENGTH])
{
static void derive_kek(uint32_t pin, const uint8_t *random_salt,
uint8_t kek[SHA256_DIGEST_LENGTH],
uint8_t keiv[SHA256_DIGEST_LENGTH]) {
#if BYTE_ORDER == BIG_ENDIAN
REVERSE32(pin, pin);
#endif
@ -358,21 +371,25 @@ static void derive_kek(uint32_t pin, const uint8_t *random_salt, uint8_t kek[SHA
}
PBKDF2_HMAC_SHA256_CTX ctx;
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t*) &pin, sizeof(pin), salt, sizeof(salt), 1);
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
sizeof(salt), 1);
for (int i = 1; i <= 5; i++) {
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
if (ui_callback && ui_message) {
progress = ((ui_total - ui_rem) * 1000 + i * DERIVE_SECS * 100) / ui_total;
progress =
((ui_total - ui_rem) * 1000 + i * DERIVE_SECS * 100) / ui_total;
ui_callback(ui_rem - i * DERIVE_SECS / 10, progress, ui_message);
}
}
pbkdf2_hmac_sha256_Final(&ctx, kek);
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t*) &pin, sizeof(pin), salt, sizeof(salt), 2);
pbkdf2_hmac_sha256_Init(&ctx, (const uint8_t *)&pin, sizeof(pin), salt,
sizeof(salt), 2);
for (int i = 6; i <= 10; i++) {
pbkdf2_hmac_sha256_Update(&ctx, PIN_ITER_COUNT / 10);
if (ui_callback && ui_message) {
progress = ((ui_total - ui_rem) * 1000 + i * DERIVE_SECS * 100) / ui_total;
progress =
((ui_total - ui_rem) * 1000 + i * DERIVE_SECS * 100) / ui_total;
ui_callback(ui_rem - i * DERIVE_SECS / 10, progress, ui_message);
}
}
@ -384,8 +401,7 @@ static void derive_kek(uint32_t pin, const uint8_t *random_salt, uint8_t kek[SHA
memzero(&salt, sizeof(salt));
}
static secbool set_pin(uint32_t pin)
{
static secbool set_pin(uint32_t pin) {
uint8_t buffer[RANDOM_SALT_SIZE + KEYS_SIZE + POLY1305_TAG_SIZE];
uint8_t *salt = buffer;
uint8_t *ekeys = buffer + RANDOM_SALT_SIZE;
@ -402,11 +418,11 @@ static secbool set_pin(uint32_t pin)
chacha20poly1305_encrypt(&ctx, cached_keys, ekeys, KEYS_SIZE);
rfc7539_finish(&ctx, 0, KEYS_SIZE, pvc);
memzero(&ctx, sizeof(ctx));
secbool ret = norcow_set(EDEK_PVC_KEY, buffer, RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE);
secbool ret =
norcow_set(EDEK_PVC_KEY, buffer, RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE);
memzero(buffer, sizeof(buffer));
if (ret == sectrue)
{
if (ret == sectrue) {
if (pin == PIN_EMPTY) {
ret = norcow_set(PIN_NOT_SET_KEY, &TRUE_BYTE, sizeof(TRUE_BYTE));
} else {
@ -418,8 +434,7 @@ static secbool set_pin(uint32_t pin)
return ret;
}
static secbool check_guard_key(const uint32_t guard_key)
{
static secbool check_guard_key(const uint32_t guard_key) {
if (guard_key % GUARD_KEY_MODULUS != GUARD_KEY_REMAINDER) {
return secfalse;
}
@ -431,7 +446,8 @@ static secbool check_guard_key(const uint32_t guard_key)
return secfalse;
}
// Check that the guard_key does not contain a run of 5 (or more) zeros or ones.
// Check that the guard_key does not contain a run of 5 (or more) zeros or
// ones.
uint32_t zero_runs = ~guard_key;
zero_runs = zero_runs & (zero_runs >> 2);
zero_runs = zero_runs & (zero_runs >> 1);
@ -449,34 +465,36 @@ static secbool check_guard_key(const uint32_t guard_key)
return sectrue;
}
static uint32_t generate_guard_key(void)
{
static uint32_t generate_guard_key(void) {
uint32_t guard_key = 0;
do {
guard_key = random_uniform((UINT32_MAX/GUARD_KEY_MODULUS) + 1) * GUARD_KEY_MODULUS + GUARD_KEY_REMAINDER;
guard_key = random_uniform((UINT32_MAX / GUARD_KEY_MODULUS) + 1) *
GUARD_KEY_MODULUS +
GUARD_KEY_REMAINDER;
} while (sectrue != check_guard_key(guard_key));
return guard_key;
}
static secbool expand_guard_key(const uint32_t guard_key, uint32_t *guard_mask, uint32_t *guard)
{
static secbool expand_guard_key(const uint32_t guard_key, uint32_t *guard_mask,
uint32_t *guard) {
if (sectrue != check_guard_key(guard_key)) {
handle_fault("guard key check");
return secfalse;
}
*guard_mask = ((guard_key & LOW_MASK) << 1) | ((~guard_key) & LOW_MASK);
*guard = (((guard_key & LOW_MASK) << 1) & guard_key) | (((~guard_key) & LOW_MASK) & (guard_key >> 1));
*guard = (((guard_key & LOW_MASK) << 1) & guard_key) |
(((~guard_key) & LOW_MASK) & (guard_key >> 1));
return sectrue;
}
static secbool pin_logs_init(uint32_t fails)
{
static secbool pin_logs_init(uint32_t fails) {
if (fails >= PIN_MAX_TRIES) {
return secfalse;
}
// The format of the PIN_LOGS_KEY entry is:
// guard_key (1 word), pin_success_log (PIN_LOG_WORDS), pin_entry_log (PIN_LOG_WORDS)
// guard_key (1 word), pin_success_log (PIN_LOG_WORDS), pin_entry_log
// (PIN_LOG_WORDS)
uint32_t logs[GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS];
logs[0] = generate_guard_key();
@ -493,26 +511,30 @@ static secbool pin_logs_init(uint32_t fails)
logs[GUARD_KEY_WORDS + i] = unused;
}
// Set the first word of the PIN entry log to indicate the requested number of fails.
logs[GUARD_KEY_WORDS + PIN_LOG_WORDS] = ((((uint32_t)0xFFFFFFFF) >> (2*fails)) & ~guard_mask) | guard;
// Set the first word of the PIN entry log to indicate the requested number of
// fails.
logs[GUARD_KEY_WORDS + PIN_LOG_WORDS] =
((((uint32_t)0xFFFFFFFF) >> (2 * fails)) & ~guard_mask) | guard;
return norcow_set(PIN_LOGS_KEY, logs, sizeof(logs));
}
/*
* Initializes the values of VERSION_KEY, EDEK_PVC_KEY, PIN_NOT_SET_KEY and PIN_LOGS_KEY using an empty PIN.
* This function should be called to initialize freshly wiped storage.
* Initializes the values of VERSION_KEY, EDEK_PVC_KEY, PIN_NOT_SET_KEY and
* PIN_LOGS_KEY using an empty PIN. This function should be called to initialize
* freshly wiped storage.
*/
static void init_wiped_storage(void)
{
static void init_wiped_storage(void) {
if (sectrue != initialized) {
// We cannot initialize the storage contents if the hardware_salt is not set.
// We cannot initialize the storage contents if the hardware_salt is not
// set.
return;
}
random_buffer(cached_keys, sizeof(cached_keys));
uint32_t version = NORCOW_VERSION;
ensure(auth_init(), "set_storage_auth_tag failed");
ensure(storage_set_encrypted(VERSION_KEY, &version, sizeof(version)), "set_storage_version failed");
ensure(storage_set_encrypted(VERSION_KEY, &version, sizeof(version)),
"set_storage_version failed");
ensure(pin_logs_init(0), "init_pin_logs failed");
ui_total = DERIVE_SECS;
ui_rem = ui_total;
@ -523,8 +545,8 @@ static void init_wiped_storage(void)
}
}
void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt, const uint16_t salt_len)
{
void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt,
const uint16_t salt_len) {
initialized = secfalse;
unlocked = secfalse;
norcow_init(&norcow_active_version);
@ -549,19 +571,20 @@ void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt, const uint
memzero(cached_keys, sizeof(cached_keys));
}
static secbool pin_fails_reset(void)
{
static secbool pin_fails_reset(void) {
const void *logs = NULL;
uint16_t len = 0;
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) || len != WORD_SIZE*(GUARD_KEY_WORDS + 2*PIN_LOG_WORDS)) {
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) ||
len != WORD_SIZE * (GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS)) {
return secfalse;
}
uint32_t guard_mask;
uint32_t guard;
wait_random();
if (sectrue != expand_guard_key(*(const uint32_t*)logs, &guard_mask, &guard)) {
if (sectrue !=
expand_guard_key(*(const uint32_t *)logs, &guard_mask, &guard)) {
return secfalse;
}
@ -573,7 +596,9 @@ static secbool pin_fails_reset(void)
return sectrue;
}
if (success_log[i] != guard) {
if (sectrue != norcow_update_word(PIN_LOGS_KEY, sizeof(uint32_t)*(i + GUARD_KEY_WORDS), entry_log[i])) {
if (sectrue != norcow_update_word(
PIN_LOGS_KEY, sizeof(uint32_t) * (i + GUARD_KEY_WORDS),
entry_log[i])) {
return secfalse;
}
}
@ -581,8 +606,7 @@ static secbool pin_fails_reset(void)
return pin_logs_init(0);
}
secbool storage_pin_fails_increase(void)
{
secbool storage_pin_fails_increase(void) {
if (sectrue != initialized) {
return secfalse;
}
@ -591,7 +615,8 @@ secbool storage_pin_fails_increase(void)
uint16_t len = 0;
wait_random();
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) || len != WORD_SIZE*(GUARD_KEY_WORDS + 2*PIN_LOG_WORDS)) {
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) ||
len != WORD_SIZE * (GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS)) {
handle_fault("no PIN logs");
return secfalse;
}
@ -599,12 +624,14 @@ secbool storage_pin_fails_increase(void)
uint32_t guard_mask;
uint32_t guard;
wait_random();
if (sectrue != expand_guard_key(*(const uint32_t*)logs, &guard_mask, &guard)) {
if (sectrue !=
expand_guard_key(*(const uint32_t *)logs, &guard_mask, &guard)) {
handle_fault("guard key expansion");
return secfalse;
}
const uint32_t *entry_log = ((const uint32_t*)logs) + GUARD_KEY_WORDS + PIN_LOG_WORDS;
const uint32_t *entry_log =
((const uint32_t *)logs) + GUARD_KEY_WORDS + PIN_LOG_WORDS;
for (size_t i = 0; i < PIN_LOG_WORDS; ++i) {
wait_random();
if ((entry_log[i] & guard_mask) != guard) {
@ -618,20 +645,22 @@ secbool storage_pin_fails_increase(void)
word = (word >> 2) | (word >> 1);
wait_random();
if (sectrue != norcow_update_word(PIN_LOGS_KEY, sizeof(uint32_t)*(i + GUARD_KEY_WORDS + PIN_LOG_WORDS), (word & ~guard_mask) | guard)) {
if (sectrue !=
norcow_update_word(
PIN_LOGS_KEY,
sizeof(uint32_t) * (i + GUARD_KEY_WORDS + PIN_LOG_WORDS),
(word & ~guard_mask) | guard)) {
handle_fault("PIN logs update");
return secfalse;
}
return sectrue;
}
}
handle_fault("PIN log exhausted");
return secfalse;
}
static uint32_t hamming_weight(uint32_t value)
{
static uint32_t hamming_weight(uint32_t value) {
value = value - ((value >> 1) & 0x55555555);
value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
value = (value + (value >> 4)) & 0x0F0F0F0F;
@ -640,14 +669,14 @@ static uint32_t hamming_weight(uint32_t value)
return value & 0x3F;
}
static secbool pin_get_fails(uint32_t *ctr)
{
static secbool pin_get_fails(uint32_t *ctr) {
*ctr = PIN_MAX_TRIES;
const void *logs = NULL;
uint16_t len = 0;
wait_random();
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) || len != WORD_SIZE*(GUARD_KEY_WORDS + 2*PIN_LOG_WORDS)) {
if (sectrue != norcow_get(PIN_LOGS_KEY, &logs, &len) ||
len != WORD_SIZE * (GUARD_KEY_WORDS + 2 * PIN_LOG_WORDS)) {
handle_fault("no PIN logs");
return secfalse;
}
@ -655,7 +684,8 @@ static secbool pin_get_fails(uint32_t *ctr)
uint32_t guard_mask;
uint32_t guard;
wait_random();
if (sectrue != expand_guard_key(*(const uint32_t*)logs, &guard_mask, &guard)) {
if (sectrue !=
expand_guard_key(*(const uint32_t *)logs, &guard_mask, &guard)) {
handle_fault("guard key expansion");
return secfalse;
}
@ -666,7 +696,9 @@ static secbool pin_get_fails(uint32_t *ctr)
volatile int current = -1;
volatile size_t i;
for (i = 0; i < PIN_LOG_WORDS; ++i) {
if ((entry_log[i] & guard_mask) != guard || (success_log[i] & guard_mask) != guard || (entry_log[i] & success_log[i]) != entry_log[i]) {
if ((entry_log[i] & guard_mask) != guard ||
(success_log[i] & guard_mask) != guard ||
(entry_log[i] & success_log[i]) != entry_log[i]) {
handle_fault("PIN logs format check");
return secfalse;
}
@ -688,7 +720,8 @@ static secbool pin_get_fails(uint32_t *ctr)
return secfalse;
}
// Strip the guard bits from the current entry word and duplicate each data bit.
// Strip the guard bits from the current entry word and duplicate each data
// bit.
wait_random();
uint32_t word = entry_log[current] & ~guard_mask;
word = ((word >> 1) | word) & LOW_MASK;
@ -705,12 +738,12 @@ static secbool pin_get_fails(uint32_t *ctr)
// Count the number of set bits in the two current words of the success log.
wait_random();
*ctr = hamming_weight(success_log[current-1] ^ entry_log[current-1]) + hamming_weight(success_log[current] ^ entry_log[current]);
*ctr = hamming_weight(success_log[current - 1] ^ entry_log[current - 1]) +
hamming_weight(success_log[current] ^ entry_log[current]);
return sectrue;
}
secbool storage_is_unlocked(void)
{
secbool storage_is_unlocked(void) {
if (sectrue != initialized) {
return secfalse;
}
@ -718,24 +751,25 @@ secbool storage_is_unlocked(void)
return unlocked;
}
void storage_lock(void)
{
void storage_lock(void) {
unlocked = secfalse;
memzero(cached_keys, sizeof(cached_keys));
memzero(authentication_sum, sizeof(authentication_sum));
}
static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv)
{
static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv) {
const void *buffer = NULL;
uint16_t len = 0;
if (sectrue != initialized || sectrue != norcow_get(EDEK_PVC_KEY, &buffer, &len) || len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
if (sectrue != initialized ||
sectrue != norcow_get(EDEK_PVC_KEY, &buffer, &len) ||
len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
handle_fault("no EDEK");
return secfalse;
}
const uint8_t *ekeys = (const uint8_t *)buffer + RANDOM_SALT_SIZE;
const uint32_t *pvc = (const uint32_t*) buffer + (RANDOM_SALT_SIZE + KEYS_SIZE)/sizeof(uint32_t);
const uint32_t *pvc = (const uint32_t *)buffer +
(RANDOM_SALT_SIZE + KEYS_SIZE) / sizeof(uint32_t);
_Static_assert(((RANDOM_SALT_SIZE + KEYS_SIZE) & 3) == 0, "PVC unaligned");
_Static_assert((PVC_SIZE & 3) == 0, "PVC size unaligned");
@ -743,13 +777,15 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv)
uint8_t tag[POLY1305_TAG_SIZE] __attribute__((aligned(sizeof(uint32_t))));
chacha20poly1305_ctx ctx;
// Decrypt the data encryption key and the storage authentication key and check the PIN verification code.
// Decrypt the data encryption key and the storage authentication key and
// check the PIN verification code.
rfc7539_init(&ctx, kek, keiv);
chacha20poly1305_decrypt(&ctx, ekeys, keys, KEYS_SIZE);
rfc7539_finish(&ctx, 0, KEYS_SIZE, tag);
memzero(&ctx, sizeof(ctx));
wait_random();
if (secequal32((const uint32_t*) tag, pvc, PVC_SIZE/sizeof(uint32_t)) != sectrue) {
if (secequal32((const uint32_t *)tag, pvc, PVC_SIZE / sizeof(uint32_t)) !=
sectrue) {
memzero(keys, sizeof(keys));
memzero(tag, sizeof(tag));
return secfalse;
@ -759,9 +795,12 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv)
memzero(tag, sizeof(tag));
// Check that the authenticated version number matches the norcow version.
// NOTE: storage_get_encrypted() calls auth_get(), which initializes the authentication_sum.
// NOTE: storage_get_encrypted() calls auth_get(), which initializes the
// authentication_sum.
uint32_t version;
if (sectrue != storage_get_encrypted(VERSION_KEY, &version, sizeof(version), &len) || len != sizeof(version) || version != norcow_active_version) {
if (sectrue !=
storage_get_encrypted(VERSION_KEY, &version, sizeof(version), &len) ||
len != sizeof(version) || version != norcow_active_version) {
handle_fault("storage version check");
return secfalse;
}
@ -769,8 +808,7 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv)
return sectrue;
}
static secbool unlock(uint32_t pin)
{
static secbool unlock(uint32_t pin) {
if (sectrue != initialized) {
return secfalse;
}
@ -786,7 +824,8 @@ static secbool unlock(uint32_t pin)
wait_random();
if (ctr >= PIN_MAX_TRIES) {
storage_wipe();
error_shutdown("Too many wrong PIN", "attempts. Storage has", "been wiped.", NULL);
error_shutdown("Too many wrong PIN", "attempts. Storage has", "been wiped.",
NULL);
return secfalse;
}
@ -810,10 +849,13 @@ static secbool unlock(uint32_t pin)
}
}
// Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and KEIV from the PIN.
// Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and
// KEIV from the PIN.
const void *salt = NULL;
uint16_t len = 0;
if (sectrue != initialized || sectrue != norcow_get(EDEK_PVC_KEY, &salt, &len) || len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
if (sectrue != initialized ||
sectrue != norcow_get(EDEK_PVC_KEY, &salt, &len) ||
len != RANDOM_SALT_SIZE + KEYS_SIZE + PVC_SIZE) {
memzero(&pin, sizeof(pin));
handle_fault("no EDEK");
return secfalse;
@ -843,7 +885,8 @@ static secbool unlock(uint32_t pin)
wait_random();
if (ctr + 1 >= PIN_MAX_TRIES) {
storage_wipe();
error_shutdown("Too many wrong PIN", "attempts. Storage has", "been wiped.", NULL);
error_shutdown("Too many wrong PIN", "attempts. Storage has",
"been wiped.", NULL);
}
return secfalse;
}
@ -856,8 +899,7 @@ static secbool unlock(uint32_t pin)
return pin_fails_reset();
}
secbool storage_unlock(uint32_t pin)
{
secbool storage_unlock(uint32_t pin) {
ui_total = DERIVE_SECS;
ui_rem = ui_total;
if (pin == PIN_EMPTY) {
@ -877,8 +919,8 @@ secbool storage_unlock(uint32_t pin)
* If val_dest is not NULL and max_len >= len, then the data is decrypted
* to val_dest using cached_dek as the decryption key.
*/
static secbool storage_get_encrypted(const uint16_t key, void *val_dest, const uint16_t max_len, uint16_t *len)
{
static secbool storage_get_encrypted(const uint16_t key, void *val_dest,
const uint16_t max_len, uint16_t *len) {
const void *val_stored = NULL;
if (sectrue != auth_get(key, &val_stored, len)) {
@ -901,7 +943,8 @@ static secbool storage_get_encrypted(const uint16_t key, void *val_dest, const u
const uint8_t *iv = (const uint8_t *)val_stored;
const uint8_t *tag_stored = (const uint8_t *)val_stored + CHACHA20_IV_SIZE;
const uint8_t *ciphertext = (const uint8_t*) val_stored + CHACHA20_IV_SIZE + POLY1305_TAG_SIZE;
const uint8_t *ciphertext =
(const uint8_t *)val_stored + CHACHA20_IV_SIZE + POLY1305_TAG_SIZE;
uint8_t tag_computed[POLY1305_TAG_SIZE];
chacha20poly1305_ctx ctx;
rfc7539_init(&ctx, cached_dek, iv);
@ -926,15 +969,16 @@ static secbool storage_get_encrypted(const uint16_t key, void *val_dest, const u
* Finds the data stored under key and writes its length to len. If val_dest is
* not NULL and max_len >= len, then the data is copied to val_dest.
*/
secbool storage_get(const uint16_t key, void *val_dest, const uint16_t max_len, uint16_t *len)
{
secbool storage_get(const uint16_t key, void *val_dest, const uint16_t max_len,
uint16_t *len) {
const uint8_t app = key >> 8;
// APP == 0 is reserved for PIN related values
if (sectrue != initialized || app == APP_STORAGE) {
return secfalse;
}
// If the top bit of APP is set, then the value is not encrypted and can be read from a locked device.
// If the top bit of APP is set, then the value is not encrypted and can be
// read from a locked device.
secbool ret = secfalse;
if ((app & FLAG_PUBLIC) != 0) {
const void *val_stored = NULL;
@ -960,16 +1004,18 @@ secbool storage_get(const uint16_t key, void *val_dest, const uint16_t max_len,
}
/*
* Encrypts the data at val using cached_dek as the encryption key and stores the ciphertext under key.
* Encrypts the data at val using cached_dek as the encryption key and stores
* the ciphertext under key.
*/
static secbool storage_set_encrypted(const uint16_t key, const void *val, const uint16_t len)
{
static secbool storage_set_encrypted(const uint16_t key, const void *val,
const uint16_t len) {
if (len > UINT16_MAX - CHACHA20_IV_SIZE - POLY1305_TAG_SIZE) {
return secfalse;
}
// Preallocate space on the flash storage.
if (sectrue != auth_set(key, NULL, CHACHA20_IV_SIZE + POLY1305_TAG_SIZE + len)) {
if (sectrue !=
auth_set(key, NULL, CHACHA20_IV_SIZE + POLY1305_TAG_SIZE + len)) {
return secfalse;
}
@ -987,9 +1033,12 @@ static secbool storage_set_encrypted(const uint16_t key, const void *val, const
rfc7539_init(&ctx, cached_dek, buffer);
rfc7539_auth(&ctx, (const uint8_t *)&key, sizeof(key));
size_t i;
for (i = 0; i + CHACHA20_BLOCK_SIZE < len; i += CHACHA20_BLOCK_SIZE, offset += CHACHA20_BLOCK_SIZE) {
chacha20poly1305_encrypt(&ctx, ((const uint8_t*) val) + i, buffer, CHACHA20_BLOCK_SIZE);
if (sectrue != norcow_update_bytes(key, offset, buffer, CHACHA20_BLOCK_SIZE)) {
for (i = 0; i + CHACHA20_BLOCK_SIZE < len;
i += CHACHA20_BLOCK_SIZE, offset += CHACHA20_BLOCK_SIZE) {
chacha20poly1305_encrypt(&ctx, ((const uint8_t *)val) + i, buffer,
CHACHA20_BLOCK_SIZE);
if (sectrue !=
norcow_update_bytes(key, offset, buffer, CHACHA20_BLOCK_SIZE)) {
memzero(&ctx, sizeof(ctx));
memzero(buffer, sizeof(buffer));
return secfalse;
@ -1008,8 +1057,7 @@ static secbool storage_set_encrypted(const uint16_t key, const void *val, const
return ret;
}
secbool storage_set(const uint16_t key, const void *val, const uint16_t len)
{
secbool storage_set(const uint16_t key, const void *val, const uint16_t len) {
const uint8_t app = key >> 8;
// APP == 0 is reserved for PIN related values
@ -1030,8 +1078,7 @@ secbool storage_set(const uint16_t key, const void *val, const uint16_t len)
return ret;
}
secbool storage_delete(const uint16_t key)
{
secbool storage_delete(const uint16_t key) {
const uint8_t app = key >> 8;
// APP == 0 is reserved for storage related values
@ -1050,8 +1097,7 @@ secbool storage_delete(const uint16_t key)
return ret;
}
secbool storage_set_counter(const uint16_t key, const uint32_t count)
{
secbool storage_set_counter(const uint16_t key, const uint32_t count) {
const uint8_t app = key >> 8;
if ((app & FLAG_PUBLIC) == 0) {
return secfalse;
@ -1065,11 +1111,11 @@ secbool storage_set_counter(const uint16_t key, const uint32_t count)
return storage_set(key, value, sizeof(value));
}
secbool storage_next_counter(const uint16_t key, uint32_t *count)
{
secbool storage_next_counter(const uint16_t key, uint32_t *count) {
const uint8_t app = key >> 8;
// APP == 0 is reserved for PIN related values
if (sectrue != initialized || app == APP_STORAGE || (app & FLAG_PUBLIC) == 0) {
if (sectrue != initialized || app == APP_STORAGE ||
(app & FLAG_PUBLIC) == 0) {
return secfalse;
}
@ -1104,22 +1150,21 @@ secbool storage_next_counter(const uint16_t key, uint32_t *count)
}
}
secbool storage_has_pin(void)
{
secbool storage_has_pin(void) {
if (sectrue != initialized) {
return secfalse;
}
const void *val = NULL;
uint16_t len;
if (sectrue != norcow_get(PIN_NOT_SET_KEY, &val, &len) || (len > 0 && *(uint8_t*)val != FALSE_BYTE)) {
if (sectrue != norcow_get(PIN_NOT_SET_KEY, &val, &len) ||
(len > 0 && *(uint8_t *)val != FALSE_BYTE)) {
return secfalse;
}
return sectrue;
}
uint32_t storage_get_pin_rem(void)
{
uint32_t storage_get_pin_rem(void) {
if (sectrue != initialized) {
return 0;
}
@ -1131,15 +1176,15 @@ uint32_t storage_get_pin_rem(void)
return PIN_MAX_TRIES - ctr;
}
secbool storage_change_pin(uint32_t oldpin, uint32_t newpin)
{
secbool storage_change_pin(uint32_t oldpin, uint32_t newpin) {
if (sectrue != initialized) {
return secfalse;
}
ui_total = 2 * DERIVE_SECS;
ui_rem = ui_total;
ui_message = (oldpin != PIN_EMPTY && newpin == PIN_EMPTY) ? VERIFYING_PIN_MSG : PROCESSING_MSG;
ui_message = (oldpin != PIN_EMPTY && newpin == PIN_EMPTY) ? VERIFYING_PIN_MSG
: PROCESSING_MSG;
if (sectrue != unlock(oldpin)) {
return secfalse;
@ -1150,8 +1195,7 @@ secbool storage_change_pin(uint32_t oldpin, uint32_t newpin)
return ret;
}
void storage_wipe(void)
{
void storage_wipe(void) {
norcow_wipe();
norcow_active_version = NORCOW_VERSION;
memzero(authentication_sum, sizeof(authentication_sum));
@ -1159,17 +1203,19 @@ void storage_wipe(void)
init_wiped_storage();
}
static void __handle_fault(const char *msg, const char *file, int line, const char *func)
{
static void __handle_fault(const char *msg, const char *file, int line,
const char *func) {
static secbool in_progress = secfalse;
// If fault handling is already in progress, then we are probably facing a fault injection attack, so wipe.
// If fault handling is already in progress, then we are probably facing a
// fault injection attack, so wipe.
if (secfalse != in_progress) {
storage_wipe();
__fatal_error("Fault detected", msg, file, line, func);
}
// We use the PIN fail counter as a fault counter. Increment the counter, check that it was incremented and halt.
// We use the PIN fail counter as a fault counter. Increment the counter,
// check that it was incremented and halt.
in_progress = sectrue;
uint32_t ctr;
if (sectrue != pin_get_fails(&ctr)) {
@ -1190,10 +1236,10 @@ static void __handle_fault(const char *msg, const char *file, int line, const ch
}
/*
* Reads the PIN fail counter in version 0 format. Returns the current number of failed PIN entries.
* Reads the PIN fail counter in version 0 format. Returns the current number of
* failed PIN entries.
*/
static secbool v0_pin_get_fails(uint32_t *ctr)
{
static secbool v0_pin_get_fails(uint32_t *ctr) {
const uint16_t V0_PIN_FAIL_KEY = 0x0001;
// The PIN_FAIL_KEY points to an area of words, initialized to
// 0xffffffff (meaning no PIN failures). The first non-zero word
@ -1221,8 +1267,7 @@ static secbool v0_pin_get_fails(uint32_t *ctr)
return sectrue;
}
static secbool storage_upgrade(void)
{
static secbool storage_upgrade(void) {
const uint16_t V0_PIN_KEY = 0x0000;
const uint16_t V0_PIN_FAIL_KEY = 0x0001;
uint16_t key = 0;
@ -1237,7 +1282,8 @@ static secbool storage_upgrade(void)
// Set the new storage version number.
uint32_t version = NORCOW_VERSION;
if (sectrue != storage_set_encrypted(VERSION_KEY, &version, sizeof(version))) {
if (sectrue !=
storage_set_encrypted(VERSION_KEY, &version, sizeof(version))) {
return secfalse;
}

@ -20,13 +20,15 @@
#ifndef __STORAGE_H__
#define __STORAGE_H__
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include "secbool.h"
typedef secbool (*PIN_UI_WAIT_CALLBACK)(uint32_t wait, uint32_t progress, const char* message);
typedef secbool (*PIN_UI_WAIT_CALLBACK)(uint32_t wait, uint32_t progress,
const char *message);
void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt, const uint16_t salt_len);
void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt,
const uint16_t salt_len);
void storage_wipe(void);
secbool storage_is_unlocked(void);
void storage_lock(void);
@ -35,7 +37,8 @@ secbool storage_has_pin(void);
secbool storage_pin_fails_increase(void);
uint32_t storage_get_pin_rem(void);
secbool storage_change_pin(const uint32_t oldpin, const uint32_t newpin);
secbool storage_get(const uint16_t key, void *val, const uint16_t max_len, uint16_t *len);
secbool storage_get(const uint16_t key, void *val, const uint16_t max_len,
uint16_t *len);
secbool storage_set(const uint16_t key, const void *val, uint16_t len);
secbool storage_delete(const uint16_t key);
secbool storage_set_counter(const uint16_t key, const uint32_t count);

@ -0,0 +1,15 @@
^\./core/embed/bootloader/protob/
^\./crypto/aes/
^\./crypto/chacha20poly1305/
^\./crypto/ed25519-donna/
^\./crypto/gui/
^\./crypto/monero/base58
^\./crypto/monero/int-util
^\./crypto/blake2
^\./crypto/check_mem
^\./crypto/groestl
^\./crypto/ripemd160
^\./crypto/segwit_addr
^\./crypto/sha2
^\./crypto/sha3
^\./legacy/vendor

@ -0,0 +1,5 @@
^\./common/
^\./core/embed/
^\./crypto/
^\./legacy/
^\./storage/

@ -0,0 +1,2 @@
^\./legacy/firmware/protob/messages_pb2\.py
^\./legacy/vendor

@ -0,0 +1,4 @@
^\./common/
^\./core/src/
^\./crypto/
^\./legacy/
Loading…
Cancel
Save