mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-16 17:42:02 +00:00
feat(core/misc): enable typing for misc app
This commit is contained in:
parent
ccd241fe55
commit
bf562cfd4b
@ -13,8 +13,8 @@ option java_outer_classname = "TrezorMessageCrypto";
|
|||||||
*/
|
*/
|
||||||
message CipherKeyValue {
|
message CipherKeyValue {
|
||||||
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
|
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
|
||||||
optional string key = 2; // key component of key:value
|
required string key = 2; // key component of key:value
|
||||||
optional bytes value = 3; // value component of key:value
|
required bytes value = 3; // value component of key:value
|
||||||
optional bool encrypt = 4; // are we encrypting (True) or decrypting (False)?
|
optional bool encrypt = 4; // are we encrypting (True) or decrypting (False)?
|
||||||
optional bool ask_on_encrypt = 5; // should we ask on encrypt operation?
|
optional bool ask_on_encrypt = 5; // should we ask on encrypt operation?
|
||||||
optional bool ask_on_decrypt = 6; // should we ask on decrypt operation?
|
optional bool ask_on_decrypt = 6; // should we ask on decrypt operation?
|
||||||
@ -26,7 +26,7 @@ message CipherKeyValue {
|
|||||||
* @end
|
* @end
|
||||||
*/
|
*/
|
||||||
message CipheredKeyValue {
|
message CipheredKeyValue {
|
||||||
optional bytes value = 1; // ciphered/deciphered value
|
required bytes value = 1; // ciphered/deciphered value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,10 +49,10 @@ message IdentityType {
|
|||||||
* @next Failure
|
* @next Failure
|
||||||
*/
|
*/
|
||||||
message SignIdentity {
|
message SignIdentity {
|
||||||
optional IdentityType identity = 1; // identity
|
required IdentityType identity = 1; // identity
|
||||||
optional bytes challenge_hidden = 2; // non-visible challenge
|
optional bytes challenge_hidden = 2 [default=""]; // non-visible challenge
|
||||||
optional string challenge_visual = 3; // challenge shown on display (e.g. date+time)
|
optional string challenge_visual = 3 [default=""]; // challenge shown on display (e.g. date+time)
|
||||||
optional string ecdsa_curve_name = 4; // ECDSA curve name to use
|
optional string ecdsa_curve_name = 4; // ECDSA curve name to use
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,8 +61,8 @@ message SignIdentity {
|
|||||||
*/
|
*/
|
||||||
message SignedIdentity {
|
message SignedIdentity {
|
||||||
optional string address = 1; // identity address
|
optional string address = 1; // identity address
|
||||||
optional bytes public_key = 2; // identity public key
|
required bytes public_key = 2; // identity public key
|
||||||
optional bytes signature = 3; // signature of the identity data
|
required bytes signature = 3; // signature of the identity data
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,8 +72,8 @@ message SignedIdentity {
|
|||||||
* @next Failure
|
* @next Failure
|
||||||
*/
|
*/
|
||||||
message GetECDHSessionKey {
|
message GetECDHSessionKey {
|
||||||
optional IdentityType identity = 1; // identity
|
required IdentityType identity = 1; // identity
|
||||||
optional bytes peer_public_key = 2; // peer's public key
|
required bytes peer_public_key = 2; // peer's public key
|
||||||
optional string ecdsa_curve_name = 3; // ECDSA curve name to use
|
optional string ecdsa_curve_name = 3; // ECDSA curve name to use
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ message GetECDHSessionKey {
|
|||||||
* @end
|
* @end
|
||||||
*/
|
*/
|
||||||
message ECDHSessionKey {
|
message ECDHSessionKey {
|
||||||
optional bytes session_key = 1; // ECDH session key
|
required bytes session_key = 1; // ECDH session key
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,6 +108,7 @@ mypy:
|
|||||||
src/main.py \
|
src/main.py \
|
||||||
src/apps/bitcoin \
|
src/apps/bitcoin \
|
||||||
src/apps/cardano \
|
src/apps/cardano \
|
||||||
|
src/apps/misc \
|
||||||
src/apps/webauthn
|
src/apps/webauthn
|
||||||
|
|
||||||
## code generation:
|
## code generation:
|
||||||
|
@ -7,8 +7,12 @@ from apps.common.confirm import require_confirm
|
|||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
from apps.common.paths import AlwaysMatchingSchema
|
from apps.common.paths import AlwaysMatchingSchema
|
||||||
|
|
||||||
|
if False:
|
||||||
|
from trezor.messages.CipherKeyValue import CipherKeyValue
|
||||||
|
from trezor.wire import Context
|
||||||
|
|
||||||
async def cipher_key_value(ctx, msg):
|
|
||||||
|
async def cipher_key_value(ctx: Context, msg: CipherKeyValue) -> CipheredKeyValue:
|
||||||
keychain = await get_keychain(ctx, "secp256k1", [AlwaysMatchingSchema])
|
keychain = await get_keychain(ctx, "secp256k1", [AlwaysMatchingSchema])
|
||||||
|
|
||||||
if len(msg.value) % 16 > 0:
|
if len(msg.value) % 16 > 0:
|
||||||
@ -30,10 +34,10 @@ async def cipher_key_value(ctx, msg):
|
|||||||
return CipheredKeyValue(value=value)
|
return CipheredKeyValue(value=value)
|
||||||
|
|
||||||
|
|
||||||
def compute_cipher_key_value(msg, seckey: bytes) -> bytes:
|
def compute_cipher_key_value(msg: CipherKeyValue, seckey: bytes) -> bytes:
|
||||||
data = msg.key
|
data = msg.key.encode()
|
||||||
data += "E1" if msg.ask_on_encrypt else "E0"
|
data += b"E1" if msg.ask_on_encrypt else b"E0"
|
||||||
data += "D1" if msg.ask_on_decrypt else "D0"
|
data += b"D1" if msg.ask_on_decrypt else b"D0"
|
||||||
data = hmac(hmac.SHA512, seckey, data).digest()
|
data = hmac(hmac.SHA512, seckey, data).digest()
|
||||||
key = data[:32]
|
key = data[:32]
|
||||||
if msg.iv and len(msg.iv) == 16:
|
if msg.iv and len(msg.iv) == 16:
|
||||||
|
@ -13,8 +13,16 @@ from apps.common.paths import AlwaysMatchingSchema
|
|||||||
|
|
||||||
from .sign_identity import serialize_identity, serialize_identity_without_proto
|
from .sign_identity import serialize_identity, serialize_identity_without_proto
|
||||||
|
|
||||||
|
if False:
|
||||||
|
from trezor.messages.GetECDHSessionKey import GetECDHSessionKey
|
||||||
|
from trezor.messages.IdentityType import IdentityType
|
||||||
|
|
||||||
async def get_ecdh_session_key(ctx, msg):
|
from apps.common.paths import Bip32Path
|
||||||
|
|
||||||
|
|
||||||
|
async def get_ecdh_session_key(
|
||||||
|
ctx: wire.Context, msg: GetECDHSessionKey
|
||||||
|
) -> ECDHSessionKey:
|
||||||
if msg.ecdsa_curve_name is None:
|
if msg.ecdsa_curve_name is None:
|
||||||
msg.ecdsa_curve_name = "secp256k1"
|
msg.ecdsa_curve_name = "secp256k1"
|
||||||
|
|
||||||
@ -34,7 +42,9 @@ async def get_ecdh_session_key(ctx, msg):
|
|||||||
return ECDHSessionKey(session_key=session_key)
|
return ECDHSessionKey(session_key=session_key)
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_ecdh_session_key(ctx, identity):
|
async def require_confirm_ecdh_session_key(
|
||||||
|
ctx: wire.Context, identity: IdentityType
|
||||||
|
) -> None:
|
||||||
lines = chunks(serialize_identity_without_proto(identity), 18)
|
lines = chunks(serialize_identity_without_proto(identity), 18)
|
||||||
proto = identity.proto.upper() if identity.proto else "identity"
|
proto = identity.proto.upper() if identity.proto else "identity"
|
||||||
text = Text("Decrypt %s" % proto)
|
text = Text("Decrypt %s" % proto)
|
||||||
@ -42,11 +52,10 @@ async def require_confirm_ecdh_session_key(ctx, identity):
|
|||||||
await require_confirm(ctx, text)
|
await require_confirm(ctx, text)
|
||||||
|
|
||||||
|
|
||||||
def get_ecdh_path(identity: str, index: int):
|
def get_ecdh_path(identity: str, index: int) -> Bip32Path:
|
||||||
identity_hash = sha256(pack("<I", index) + identity).digest()
|
identity_hash = sha256(pack("<I", index) + identity.encode()).digest()
|
||||||
|
|
||||||
address_n = (17,) + unpack("<IIII", identity_hash[:16])
|
address_n = [HARDENED | x for x in (17,) + unpack("<IIII", identity_hash[:16])]
|
||||||
address_n = [HARDENED | x for x in address_n]
|
|
||||||
|
|
||||||
return address_n
|
return address_n
|
||||||
|
|
||||||
|
@ -5,8 +5,12 @@ from trezor.ui.text import Text
|
|||||||
|
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
|
|
||||||
|
if False:
|
||||||
|
from trezor.wire import Context
|
||||||
|
from trezor.messages.GetEntropy import GetEntropy
|
||||||
|
|
||||||
async def get_entropy(ctx, msg):
|
|
||||||
|
async def get_entropy(ctx: Context, msg: GetEntropy) -> Entropy:
|
||||||
text = Text("Confirm entropy")
|
text = Text("Confirm entropy")
|
||||||
text.bold("Do you really want", "to send entropy?")
|
text.bold("Do you really want", "to send entropy?")
|
||||||
text.normal("Continue only if you", "know what you are doing!")
|
text.normal("Continue only if you", "know what you are doing!")
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
from ustruct import pack, unpack
|
from ustruct import pack, unpack
|
||||||
|
|
||||||
from trezor import ui
|
from trezor import ui, wire
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
from trezor.messages.SignedIdentity import SignedIdentity
|
from trezor.messages.SignedIdentity import SignedIdentity
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
|
|
||||||
from apps.common import HARDENED, coins
|
from apps.common import HARDENED, coininfo
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
from apps.common.paths import AlwaysMatchingSchema
|
from apps.common.paths import AlwaysMatchingSchema
|
||||||
|
|
||||||
|
if False:
|
||||||
|
from typing import List, Optional, Union
|
||||||
|
|
||||||
async def sign_identity(ctx, msg):
|
from trezor.messages.IdentityType import IdentityType
|
||||||
|
from trezor.messages.SignIdentity import SignIdentity
|
||||||
|
from trezor.ui.text import TextContent
|
||||||
|
|
||||||
|
from apps.common.paths import Bip32Path
|
||||||
|
|
||||||
|
|
||||||
|
async def sign_identity(ctx: wire.Context, msg: SignIdentity) -> SignedIdentity:
|
||||||
if msg.ecdsa_curve_name is None:
|
if msg.ecdsa_curve_name is None:
|
||||||
msg.ecdsa_curve_name = "secp256k1"
|
msg.ecdsa_curve_name = "secp256k1"
|
||||||
|
|
||||||
@ -24,9 +33,10 @@ async def sign_identity(ctx, msg):
|
|||||||
address_n = get_identity_path(identity, msg.identity.index or 0)
|
address_n = get_identity_path(identity, msg.identity.index or 0)
|
||||||
node = keychain.derive(address_n)
|
node = keychain.derive(address_n)
|
||||||
|
|
||||||
coin = coins.by_name("Bitcoin")
|
coin = coininfo.by_name("Bitcoin")
|
||||||
if msg.ecdsa_curve_name == "secp256k1":
|
if msg.ecdsa_curve_name == "secp256k1":
|
||||||
address = node.address(coin.address_type) # hardcoded bitcoin address type
|
# hardcoded bitcoin address type
|
||||||
|
address: Optional[str] = node.address(coin.address_type)
|
||||||
else:
|
else:
|
||||||
address = None
|
address = None
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
@ -70,8 +80,10 @@ async def sign_identity(ctx, msg):
|
|||||||
return SignedIdentity(address=address, public_key=pubkey, signature=signature)
|
return SignedIdentity(address=address, public_key=pubkey, signature=signature)
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_sign_identity(ctx, identity, challenge_visual):
|
async def require_confirm_sign_identity(
|
||||||
lines = []
|
ctx: wire.Context, identity: IdentityType, challenge_visual: Optional[str]
|
||||||
|
) -> None:
|
||||||
|
lines: List[TextContent] = []
|
||||||
if challenge_visual:
|
if challenge_visual:
|
||||||
lines.append(challenge_visual)
|
lines.append(challenge_visual)
|
||||||
|
|
||||||
@ -84,7 +96,7 @@ async def require_confirm_sign_identity(ctx, identity, challenge_visual):
|
|||||||
await require_confirm(ctx, text)
|
await require_confirm(ctx, text)
|
||||||
|
|
||||||
|
|
||||||
def serialize_identity(identity):
|
def serialize_identity(identity: IdentityType) -> str:
|
||||||
s = ""
|
s = ""
|
||||||
if identity.proto:
|
if identity.proto:
|
||||||
s += identity.proto + "://"
|
s += identity.proto + "://"
|
||||||
@ -99,7 +111,7 @@ def serialize_identity(identity):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def serialize_identity_without_proto(identity):
|
def serialize_identity_without_proto(identity: IdentityType) -> str:
|
||||||
proto = identity.proto
|
proto = identity.proto
|
||||||
identity.proto = None # simplify serialized identity string
|
identity.proto = None # simplify serialized identity string
|
||||||
s = serialize_identity(identity)
|
s = serialize_identity(identity)
|
||||||
@ -107,17 +119,20 @@ def serialize_identity_without_proto(identity):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def get_identity_path(identity: str, index: int):
|
def get_identity_path(identity: str, index: int) -> Bip32Path:
|
||||||
identity_hash = sha256(pack("<I", index) + identity).digest()
|
identity_hash = sha256(pack("<I", index) + identity.encode()).digest()
|
||||||
|
|
||||||
address_n = (13,) + unpack("<IIII", identity_hash[:16])
|
address_n = [HARDENED | x for x in (13,) + unpack("<IIII", identity_hash[:16])]
|
||||||
address_n = [HARDENED | x for x in address_n]
|
|
||||||
|
|
||||||
return address_n
|
return address_n
|
||||||
|
|
||||||
|
|
||||||
def sign_challenge(
|
def sign_challenge(
|
||||||
seckey: bytes, challenge_hidden: bytes, challenge_visual: str, sigtype, curve: str
|
seckey: bytes,
|
||||||
|
challenge_hidden: bytes,
|
||||||
|
challenge_visual: str,
|
||||||
|
sigtype: Union[str, coininfo.CoinInfo],
|
||||||
|
curve: str,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
|
|
||||||
@ -133,19 +148,22 @@ def sign_challenge(
|
|||||||
data = challenge_hidden
|
data = challenge_hidden
|
||||||
elif sigtype == "signify":
|
elif sigtype == "signify":
|
||||||
if curve != "ed25519":
|
if curve != "ed25519":
|
||||||
raise ValueError("Unsupported curve")
|
raise wire.DataError("Unsupported curve")
|
||||||
data = challenge_hidden
|
data = challenge_hidden
|
||||||
elif sigtype == "ssh":
|
elif sigtype == "ssh":
|
||||||
if curve != "ed25519":
|
if curve != "ed25519":
|
||||||
data = sha256(challenge_hidden).digest()
|
data = sha256(challenge_hidden).digest()
|
||||||
else:
|
else:
|
||||||
data = challenge_hidden
|
data = challenge_hidden
|
||||||
else:
|
elif isinstance(sigtype, coininfo.CoinInfo):
|
||||||
# sigtype is coin
|
# sigtype is coin
|
||||||
challenge = (
|
challenge = (
|
||||||
sha256(challenge_hidden).digest() + sha256(challenge_visual).digest()
|
sha256(challenge_hidden).digest()
|
||||||
|
+ sha256(challenge_visual.encode()).digest()
|
||||||
)
|
)
|
||||||
data = message_digest(sigtype, challenge)
|
data = message_digest(sigtype, challenge)
|
||||||
|
else:
|
||||||
|
raise wire.DataError("Unsupported sigtype")
|
||||||
|
|
||||||
if curve == "secp256k1":
|
if curve == "secp256k1":
|
||||||
signature = secp256k1.sign(seckey, data)
|
signature = secp256k1.sign(seckey, data)
|
||||||
@ -154,7 +172,7 @@ def sign_challenge(
|
|||||||
elif curve == "ed25519":
|
elif curve == "ed25519":
|
||||||
signature = ed25519.sign(seckey, data)
|
signature = ed25519.sign(seckey, data)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unknown curve")
|
raise wire.DataError("Unknown curve")
|
||||||
|
|
||||||
if curve == "ed25519":
|
if curve == "ed25519":
|
||||||
signature = b"\x00" + signature
|
signature = b"\x00" + signature
|
||||||
|
Loading…
Reference in New Issue
Block a user