def apdu_exchange(self, ins, data=b"", p1=0, p2=0): apdu = bytes([self.cla, ins, p1, p2]) apdu += serialize(data) response = self.raw_exchange(apdu) status_word = int.from_bytes(response[-2:], "big") if status_word != 0x9000 and ((status_word >> 8) != 0x61): possible_cause = "Unknown reason" if status_word == 0x6982: possible_cause = ( "Have you uninstalled the existing CA with resetCustomCA first?" ) elif status_word == 0x6985: possible_cause = "Condition of use not satisfied (denied by the user?)" elif status_word == 0x6A84 or status_word == 0x6A85: possible_cause = "Not enough space?" elif status_word == 0x6A83: possible_cause = ( "Maybe this app requires a library to be installed first?" ) elif status_word == 0x6484: possible_cause = "Are you using the correct targetId?" elif status_word == 0x69D5: possible_cause = "Cannot create custom secure channels on this device" raise CommException( "Invalid status %04x (%s)" % (status_word, possible_cause), status_word, data, ) return response[:-2]
def delete_app(self, app: Union[str, bytes]): if isinstance(app, str): self.apdu_secure_exchange(LedgerSecureIns.DELETE_APP, serialize(app.encode())) elif isinstance(app, bytes) and len(app) == 32: self.apdu_secure_exchange(LedgerSecureIns.DELETE_APP_BY_HASH, app) else: raise TypeError("app parameter must be string or digest")
def receive_certificate_chain(self): cert_chain = [] if self.cert_chain is not None: cert_chain.append(self.cert_chain) else: data_to_sign = bytes([CERT_ROLE_SIGNER]) + self.master_public master_signature = self.master_private.sign(data_to_sign) cert_chain.append( serialize(self.master_public) + serialize(master_signature)) # Provide the ephemeral certificate, signed with the master public key self.ephemeral_private = PrivateKey() ephemeral_public = self.ephemeral_private.pubkey.serialize( compressed=False) # print("Using ephemeral key {}".format(ephemeral_public.hex())) data_to_sign = (bytes([CERT_ROLE_SIGNER_EPHEMERAL]) + self.server_nonce + self.device_nonce + ephemeral_public) signature = self.master_private.sign(data_to_sign) cert_chain.append(serialize(ephemeral_public) + serialize(signature)) return cert_chain
def receive_certificate_chain(self): # Get signed public key response = self.query(self.device_nonce) server_signature = response public_key = self.public_key return [serialize(public_key) + serialize(server_signature)]
def install_ca(self, name: str, public_key: bytes): data = serialize(name.encode()) + serialize(public_key) self.apdu_secure_exchange(LedgerSecureIns.SETUP_CUSTOM_CERTIFICATE, data)
def apdu_exchange(self, ins, data, p1, p2) -> bytes: apdu = bytes([self.cla, ins, p1, p2]) apdu += serialize(data) return bytes.fromhex(self.cassette[apdu.hex()])