Merge branch 'fixes'

This commit is contained in:
Roman Zeyde
2023-02-04 19:09:05 +02:00
8 changed files with 40 additions and 37 deletions

View File

@@ -36,11 +36,13 @@ def _convert_public_key(ecdsa_curve_name, result):
class LedgerNanoS(interface.Device): class LedgerNanoS(interface.Device):
"""Connection to Ledger Nano S device.""" """Connection to Ledger Nano S device."""
LEDGER_APP_NAME = "SSH/PGP Agent" LEDGER_APP_NAME = "SSH/PGP Agent"
ledger_app_version = None ledger_app_version = None
ledger_app_supports_end_of_frame_byte = True ledger_app_supports_end_of_frame_byte = True
def get_app_name_and_version(self, dongle): def get_app_name_and_version(self, dongle):
"""Retrieve currently running Ledger application name and its version string."""
device_version_answer = dongle.exchange(binascii.unhexlify('B001000000')) device_version_answer = dongle.exchange(binascii.unhexlify('B001000000'))
offset = 1 offset = 1
app_name_length = struct.unpack_from("B", device_version_answer, offset)[0] app_name_length = struct.unpack_from("B", device_version_answer, offset)[0]
@@ -50,7 +52,7 @@ class LedgerNanoS(interface.Device):
app_version_length = struct.unpack_from("B", device_version_answer, offset)[0] app_version_length = struct.unpack_from("B", device_version_answer, offset)[0]
offset += 1 offset += 1
app_version = device_version_answer[offset: offset + app_version_length] app_version = device_version_answer[offset: offset + app_version_length]
log.debug("running app {}, version {}".format(app_name, app_version)) log.debug("running app %s, version %s", app_name, app_version)
return (app_name.decode(), app_version.decode()) return (app_name.decode(), app_version.decode())
@classmethod @classmethod
@@ -98,6 +100,7 @@ class LedgerNanoS(interface.Device):
def sign(self, identity, blob): def sign(self, identity, blob):
"""Sign given blob and return the signature (as bytes).""" """Sign given blob and return the signature (as bytes)."""
# pylint: disable=too-many-locals,too-many-branches
path = _expand_path(identity.get_bip32_address(ecdh=False)) path = _expand_path(identity.get_bip32_address(ecdh=False))
offset = 0 offset = 0
result = None result = None

View File

@@ -289,7 +289,7 @@ class OnlyKey(interface.Device):
log.info('received= %s', repr(result)) log.info('received= %s', repr(result))
return bytes(result) return bytes(result)
raise Exception('failed to sign challenge') raise interface.Error('failed to sign challenge')
def ecdh(self, identity, pubkey): def ecdh(self, identity, pubkey):
"""Get shared session key using Elliptic Curve Diffie-Hellman.""" """Get shared session key using Elliptic Curve Diffie-Hellman."""

View File

@@ -164,7 +164,7 @@ class Handler:
# We assume the first user ID is used to generate TREZOR-based GPG keys. # We assume the first user ID is used to generate TREZOR-based GPG keys.
user_id = user_ids[0]['value'].decode('utf-8') user_id = user_ids[0]['value'].decode('utf-8')
curve_name = protocol.get_curve_name_by_oid(pubkey_dict['curve_oid']) curve_name = protocol.get_curve_name_by_oid(pubkey_dict['curve_oid'])
ecdh = (pubkey_dict['algo'] == protocol.ECDH_ALGO_ID) ecdh = pubkey_dict['algo'] == protocol.ECDH_ALGO_ID
identity = client.create_identity(user_id=user_id, curve_name=curve_name) identity = client.create_identity(user_id=user_id, curve_name=curve_name)
verifying_key = self.client.pubkey(identity=identity, ecdh=ecdh) verifying_key = self.client.pubkey(identity=identity, ecdh=ecdh)

View File

@@ -11,7 +11,7 @@ log = logging.getLogger(__name__)
def create_primary(user_id, pubkey, signer_func, secret_bytes=b''): def create_primary(user_id, pubkey, signer_func, secret_bytes=b''):
"""Export new primary GPG public key, ready for "gpg2 --import".""" """Export new primary GPG public key, ready for "gpg2 --import"."""
pubkey_packet = protocol.packet(tag=(5 if secret_bytes else 6), pubkey_packet = protocol.packet(tag=(5 if secret_bytes else 6),
blob=(pubkey.data() + secret_bytes)) blob=pubkey.data() + secret_bytes)
user_id_bytes = user_id.encode('utf-8') user_id_bytes = user_id.encode('utf-8')
user_id_packet = protocol.packet(tag=13, blob=user_id_bytes) user_id_packet = protocol.packet(tag=13, blob=user_id_bytes)
data_to_sign = (pubkey.data_to_hash() + user_id_packet[:1] + data_to_sign = (pubkey.data_to_hash() + user_id_packet[:1] +
@@ -51,7 +51,7 @@ def create_primary(user_id, pubkey, signer_func, secret_bytes=b''):
def create_subkey(primary_bytes, subkey, signer_func, secret_bytes=b''): def create_subkey(primary_bytes, subkey, signer_func, secret_bytes=b''):
"""Export new subkey to GPG primary key.""" """Export new subkey to GPG primary key."""
subkey_packet = protocol.packet(tag=(7 if secret_bytes else 14), subkey_packet = protocol.packet(tag=(7 if secret_bytes else 14),
blob=(subkey.data() + secret_bytes)) blob=subkey.data() + secret_bytes)
packets = list(decode.parse_packets(io.BytesIO(primary_bytes))) packets = list(decode.parse_packets(io.BytesIO(primary_bytes)))
primary, user_id, signature = packets[:3] primary, user_id, signature = packets[:3]

View File

@@ -134,7 +134,7 @@ def server_thread(sock, handle_conn, quit_event):
break break
# Handle connections from SSH concurrently. # Handle connections from SSH concurrently.
threading.Thread(target=handle_conn, threading.Thread(target=handle_conn,
kwargs=dict(conn=conn)).start() kwargs={'conn': conn}).start()
log.debug('server thread stopped') log.debug('server thread stopped')

View File

@@ -138,9 +138,9 @@ def serve(handler, sock_path, timeout=UNIX_SOCKET_TIMEOUT):
handle_conn = functools.partial(server.handle_connection, handle_conn = functools.partial(server.handle_connection,
handler=handler, handler=handler,
mutex=device_mutex) mutex=device_mutex)
kwargs = dict(sock=sock, kwargs = {'sock': sock,
handle_conn=handle_conn, 'handle_conn': handle_conn,
quit_event=quit_event) 'quit_event': quit_event}
with server.spawn(server.server_thread, kwargs): with server.spawn(server.server_thread, kwargs):
try: try:
yield environ yield environ

View File

@@ -16,33 +16,33 @@ log = logging.getLogger(__name__)
# Taken from https://github.com/openssh/openssh-portable/blob/master/authfd.h # Taken from https://github.com/openssh/openssh-portable/blob/master/authfd.h
COMMANDS = dict( COMMANDS = {
SSH_AGENTC_REQUEST_RSA_IDENTITIES=1, "SSH_AGENTC_REQUEST_RSA_IDENTITIES": 1,
SSH_AGENT_RSA_IDENTITIES_ANSWER=2, "SSH_AGENT_RSA_IDENTITIES_ANSWER": 2,
SSH_AGENTC_RSA_CHALLENGE=3, "SSH_AGENTC_RSA_CHALLENGE": 3,
SSH_AGENT_RSA_RESPONSE=4, "SSH_AGENT_RSA_RESPONSE": 4,
SSH_AGENT_FAILURE=5, "SSH_AGENT_FAILURE": 5,
SSH_AGENT_SUCCESS=6, "SSH_AGENT_SUCCESS": 6,
SSH_AGENTC_ADD_RSA_IDENTITY=7, "SSH_AGENTC_ADD_RSA_IDENTITY": 7,
SSH_AGENTC_REMOVE_RSA_IDENTITY=8, "SSH_AGENTC_REMOVE_RSA_IDENTITY": 8,
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES=9, "SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES": 9,
SSH2_AGENTC_REQUEST_IDENTITIES=11, "SSH2_AGENTC_REQUEST_IDENTITIES": 11,
SSH2_AGENT_IDENTITIES_ANSWER=12, "SSH2_AGENT_IDENTITIES_ANSWER": 12,
SSH2_AGENTC_SIGN_REQUEST=13, "SSH2_AGENTC_SIGN_REQUEST": 13,
SSH2_AGENT_SIGN_RESPONSE=14, "SSH2_AGENT_SIGN_RESPONSE": 14,
SSH2_AGENTC_ADD_IDENTITY=17, "SSH2_AGENTC_ADD_IDENTITY": 17,
SSH2_AGENTC_REMOVE_IDENTITY=18, "SSH2_AGENTC_REMOVE_IDENTITY": 18,
SSH2_AGENTC_REMOVE_ALL_IDENTITIES=19, "SSH2_AGENTC_REMOVE_ALL_IDENTITIES": 19,
SSH_AGENTC_ADD_SMARTCARD_KEY=20, "SSH_AGENTC_ADD_SMARTCARD_KEY": 20,
SSH_AGENTC_REMOVE_SMARTCARD_KEY=21, "SSH_AGENTC_REMOVE_SMARTCARD_KEY": 21,
SSH_AGENTC_LOCK=22, "SSH_AGENTC_LOCK": 22,
SSH_AGENTC_UNLOCK=23, "SSH_AGENTC_UNLOCK": 23,
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED=24, "SSH_AGENTC_ADD_RSA_ID_CONSTRAINED": 24,
SSH2_AGENTC_ADD_ID_CONSTRAINED=25, "SSH2_AGENTC_ADD_ID_CONSTRAINED": 25,
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED=26, "SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED": 26,
SSH_AGENTC_EXTENSION=27, "SSH_AGENTC_EXTENSION": 27,
SSH_AGENT_EXTENSION_FAILURE=28, "SSH_AGENT_EXTENSION_FAILURE": 28,
) }
def msg_code(name): def msg_code(name):

View File

@@ -102,7 +102,7 @@ def test_spawn():
def thread(x): def thread(x):
obj.append(x) obj.append(x)
with server.spawn(thread, dict(x=1)): with server.spawn(thread, {'x': 1}):
pass pass
assert obj == [1] assert obj == [1]