Beispiel #1
0
def decrypt(prx, meta, **kwargs):
    p = prx_header_8(prx)
    xorbuf = kirk.kirk7(meta['seed'], meta['key'])

    # calculate SHA1 of header
    h = SHA1.new()
    h.update(xorbuf[:0x14])
    h.update(p.vanity_area())
    h.update(p.kirk_block())
    h.update(p.kirk_metadata())
    h.update(p.elf_info())

    if h.digest() != p.sha1_hash():
        print("bad SHA1")
        return False

    # decrypt the kirk header
    header = xor(p.kirk_block(), xorbuf[0x14:0x84])
    header = kirk.kirk7(header, meta['key'])
    header = xor(header, xorbuf[0x20:])

    # prepare the kirk block
    block = header + p.kirk_metadata() + p.elf_info() + prx[0x150:]

    # do the decryption
    return kirk.kirk1(block)
Beispiel #2
0
def decrypt(prx, meta, **kwargs):
    xorbuf = expand_seed(meta['seed'], meta['key'])

    # check if range contains nonzero
    if any(x != 0 for x in prx[0xD4:0xD4 + 0x30]):
        return False

    p = prx_header_9(prx)

    print(meta['pubkey'])
    print(p.prx_ecdsa().hex())

    # check ECDSA signature
    # kirk.kirk11(bytes.fromhex(meta['pubkey']), p.prx_ecdsa(
    # ), prx[4:0x104] + b'\x00'*0x28 + prx[0x12C:])

    h2 = SHA1.new()
    h2.update(prx[4:0x104] + b'\x00' * 0x28 + prx[0x12C:])
    print(h2.hexdigest())

    # decrypt the header information
    p.decrypt_header(meta['key'])

    # calculate SHA1 of header
    h = SHA1.new()
    h.update(p.tag())
    h.update(xorbuf[:0x10])
    h.update(b'\x00' * 0x58)
    h.update(p.btcnf_id())
    h.update(p.kirk_aes_key())
    h.update(p.kirk_cmac_key())
    h.update(p.kirk_cmac_header_hash())
    h.update(p.kirk_cmac_data_hash())
    h.update(p.kirk_metadata())
    h.update(p.elf_info())

    # sanity check that our SHA1 actually matches
    if h.digest() != p.sha1_hash():
        return False

    # decrypt the kirk block
    header = xor(p.kirk_block(), xorbuf[0x10:0x50])
    header = kirk.kirk7(header, meta['key'])
    header = xor(header, xorbuf[0x50:])

    # prepare the kirk block
    block = header + b'\x00' * 0x30
    block = set_kirk_cmd_1(block)
    block = block + p.kirk_metadata() + b'\x00'*0x10 + \
        p.elf_info() + prx[0x150:]

    return kirk.kirk1(block)
Beispiel #3
0
    def _demangle(self, block):
        if self._version == 5:
            block = xor(
                block,
                math.ceil(len(block) / 0x10) *
                bytes.fromhex('D869B895336B633498B9FC3CB7262BD7')[:len(block)])

        block = kirk.kirk7(block, 0x55)

        if self._version == 5:
            block = xor(
                block,
                math.ceil(len(block) / 0x10) *
                bytes.fromhex('0DA09084AF9EB6E2D294F2AAEF996871')[:len(block)])

        return block
Beispiel #4
0
def encrypt(prx, meta, id=None):
    xorbuf = expand_seed(meta['seed'], meta['key'])

    # encrypt as kirk1
    encrypted = kirk.kirk1_encrypt_ecdsa(prx[0x150:], salt=prx[:0x80])

    header = xor(encrypted[:0x40], xorbuf[0x50:])
    header = kirk.kirk4(header, meta['key'])
    header = xor(header, xorbuf[0x10:0x50])

    # calculate an id
    if id == None:
        id = Random.get_random_bytes(16)

    elif type(id) is str:
        id = '{:16.16}'.format(id).encode()

    id = kirk.kirk7(id, meta['key'])

    # create a prx header
    prx_header = prx_header_6()
    prx_header.set_elf_info(prx[:0x80])
    prx_header.set_kirk_block(header)
    prx_header.set_kirk_ecdsa_data_sig_end(encrypted[0x40:0x60])
    prx_header.set_kirk_metadata(encrypted[0x70:0x80])
    prx_header.set_btcnf_id(id)
    prx_header.set_tag(prx[0xD0:0xD4])

    # calculate SHA1 of header
    h = SHA1.new()
    h.update(prx_header.tag())
    h.update(xorbuf[:0x10])
    h.update(b'\x00' * 0x38)
    h.update(prx_header.kirk_ecdsa_data_sig_end())
    h.update(prx_header.btcnf_id())
    h.update(prx_header.kirk_aes_key())
    h.update(prx_header.kirk_ecdsa_header_sig())
    h.update(prx_header.kirk_ecdsa_data_sig_begin())
    h.update(prx_header.kirk_metadata())
    h.update(prx_header.elf_info())
    prx_header.set_sha1_hash(h.digest())

    # encrypt the header and return the complete PRX
    prx_header.encrypt_header(meta['key'])
    return prx_header.prx() + encrypted[0x90 + 0x80:]
Beispiel #5
0
def decrypt(prx, meta):
    xorbuf = expand_seed(meta['seed'], meta['key'])

    # check if range contains nonzero
    if any(x != 0 for x in prx[0xD4:0xD4 + 0x38]):
        return False

    p = prx_header_6(prx)

    # decrypt the header information
    p.decrypt_header(meta['key'])

    # calculate SHA1 of header
    h = SHA1.new()
    h.update(p.tag())
    h.update(xorbuf[:0x10])
    h.update(b'\x00' * 0x38)
    h.update(p.kirk_ecdsa_data_sig_end())
    h.update(p.btcnf_id())
    h.update(p.kirk_aes_key())
    h.update(p.kirk_ecdsa_header_sig())
    h.update(p.kirk_ecdsa_data_sig_begin())
    h.update(p.kirk_metadata())
    h.update(p.elf_info())

    if h.digest() != p.sha1_hash():
        print("bad SHA1")
        return False

    # decrypt the kirk header
    header = xor(p.kirk_block(), xorbuf[0x10:0x50])
    header = kirk.kirk7(header, meta['key'])
    header = xor(header, xorbuf[0x50:])

    # prepare the kirk block
    block = header + p.kirk_ecdsa_data_sig_end() + b'\x00' * 0x10
    block = set_kirk_cmd_1(block)
    block = set_kirk_cmd_1_ecdsa(block)
    block = block + p.kirk_metadata() + b'\x00'*0x10 + \
        p.elf_info() + prx[0x150:]

    # do the decryption
    return kirk.kirk1(block)
Beispiel #6
0
def encrypt(prx, meta, vanity=None, **kwargs):
    xorbuf = kirk.kirk7(meta['seed'], meta['key'])

    # encrypt as kirk1
    encrypted = kirk.kirk1_encrypt_ecdsa(prx[0x150:], salt=prx[:0x80])

    header = xor(encrypted[:0x70], xorbuf[0x20:])
    header = kirk.kirk4(header, meta['key'])
    header = xor(header, xorbuf[0x14:0x84])

    # calculate some vanity
    if vanity == None:
        vanity = Random.get_random_bytes(0x28)

    elif type(vanity) is str:
        vanity = '{:40.40}'.format(vanity).encode()

    # create a prx header
    prx_header = prx_header_8()
    prx_header.set_elf_info(prx[:0x80])
    prx_header.set_kirk_block(header)
    prx_header.set_kirk_metadata(encrypted[0x70:0x90])
    prx_header.set_vanity_area(vanity)
    prx_header.set_tag(prx[0xD0:0xD4])

    # calculate SHA1 of header
    h = SHA1.new()
    h.update(xorbuf[:0x14])
    h.update(prx_header.vanity_area())
    h.update(prx_header.kirk_block())
    h.update(prx_header.kirk_metadata())
    h.update(prx_header.elf_info())
    prx_header.set_sha1_hash(h.digest())

    # encrypt the header and return the complete PRX
    return prx_header.prx() + encrypted[0x90 + 0x80:]
Beispiel #7
0
def verifyAnchorCanData(current_anchor_random_number, can_id_key, nonce,
                        ciphertext):
    """Decrypt and verify a CAN data frame

    Parameters

    - **current_anchor_random_number** *byte string* : last anchor random number received by the ECU

    - **can_id_key** *byte string* : private key corresponding to the CAN ID used for this communication

    - **nonce** *byte string* : initial vector or latest CAN frame for the CAN ID used for this communication

    - **ciphertext** *byte string* : encrypted CAN data frame
    """
    # Key derivation function
    salt = current_anchor_random_number
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                     length=64,
                     salt=salt,
                     iterations=10000,
                     backend=default_backend())
    kdf_output = kdf.derive(can_id_key)
    ctr_counter = Counter.new(
        120, nonce
    )  #counter size will be 120 bits + *nonce size* bits. Counter size should be as big as block size (https://pythonhosted.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CTR)
    block_cipher = AES.new(can_id_key, AES.MODE_CTR, counter=ctr_counter)
    derived_key = block_cipher.encrypt(kdf_output)[:8]

    # Decryption
    data_frame = xor(derived_key, ciphertext)
    message = data_frame[:6]
    counter = data_frame[6:7]
    received_hash = data_frame[7:8]

    # Authentication check
    hmac = HMAC.new(kdf_output, digestmod=SHA256)
    hmac.update(message + counter + current_anchor_random_number)
    authentication = hmac.hexdigest().encode()[:1]

    #TODO: add Ta (counter) check

    if authentication == received_hash:
        a = 1
        #print("\nSuccesful authentication, message is: " + str("".join("\\x%02x" % i for i in message)))
    else:
        a = 2
Beispiel #8
0
def verifyAnchorFrame(gateway_private_key, gateway_initial_vector, ciphertext):
    """Decrypt and verify an anchor frame

    Parameters

    - **gateway_private_key** *byte string* : private key of the gateway ECU

    - **initial vector** *byte string* : initial vector of the gateway ECU

    - **ciphertext** *byte string* : encrypted anchor frame
    """
    # Key derivation function
    salt = gateway_initial_vector
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                     length=64,
                     salt=salt,
                     iterations=10000,
                     backend=default_backend())
    kdf_output = kdf.derive(gateway_private_key)
    ctr_counter = Counter.new(
        120, gateway_initial_vector
    )  #counter size will be 120 bits + *gateway_initial_vector size* bits. Counter size should be as big as block size (https://pythonhosted.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CTR)
    block_cipher = AES.new(gateway_private_key,
                           AES.MODE_CTR,
                           counter=ctr_counter)
    derived_key = block_cipher.encrypt(kdf_output)

    # Decryption
    data_frame = xor(derived_key, ciphertext)
    anchor_random_number = data_frame[:56]
    received_hash = data_frame[56:64]

    # Authentication check
    hmac = HMAC.new(kdf_output, digestmod=SHA256)
    hmac.update(anchor_random_number)
    authentication = hmac.hexdigest().encode()[:8]

    if authentication == received_hash:
        print("\nSuccesful authentication, anchor random number is: " +
              str("".join("\\x%02x" % i for i in anchor_random_number)))
    else:
        print("\nFailed authentication, can't retrieve anchor random number!")
Beispiel #9
0
def generateAnchorCanData(current_anchor_random_number, message, can_id_key,
                          can_id_counter, nonce):
    """Return an encrypted CAN data frame

    Parameters

    - **current_anchor_random_number** *byte string* : last anchor random number received by the ECU

    - **message** *byte string* : data to be sent securely

    - **can_id_key** *byte string* : private key corresponding to the CAN ID used for this communication

    - **can_id_counter** *byte string* : local counter corresponding to the CAN ID used for this communication

    - **nonce** *byte string* : initial vector or latest CAN frame for the CAN ID used for this communication
    """
    # TODO: understand why can_id_counter is only 2 bits while documentation recommends 4bits
    # Key derivation function
    salt = current_anchor_random_number
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                     length=64,
                     salt=salt,
                     iterations=10000,
                     backend=default_backend())
    kdf_output = kdf.derive(can_id_key)
    ctr_counter = Counter.new(
        120, nonce
    )  #counter size will be 120 bits + *nonce size* bits. Counter size should be as big as block size (https://pythonhosted.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CTR)
    block_cipher = AES.new(can_id_key, AES.MODE_CTR, counter=ctr_counter)
    derived_key = block_cipher.encrypt(kdf_output)[:8]

    # Authentication
    hmac = HMAC.new(kdf_output, digestmod=SHA256)
    hmac.update(message + can_id_counter + current_anchor_random_number)
    authentication = hmac.hexdigest().encode()[:1]

    # Encryption
    data_frame = message + can_id_counter + authentication
    ciphertext = xor(data_frame, derived_key)

    return ciphertext
Beispiel #10
0
def generateAnchorFrame(anchor_random_number, gateway_private_key,
                        gateway_initial_vector):
    """Return an anchor frame (an encrypted random number ready to be securely sent to ECUs)

    Parameters

    - **anchor_random_number** *byte string* : random number to send to the ECUs

    - **gateway_private_key** *byte string* : private key of the gateway ECU

    - **initial vector** *byte string* : initial vector of the gateway ECU
    """
    # Key derivation function
    salt = gateway_initial_vector
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                     length=64,
                     salt=salt,
                     iterations=10000,
                     backend=default_backend())
    kdf_output = kdf.derive(gateway_private_key)
    ctr_counter = Counter.new(
        120, gateway_initial_vector
    )  #counter size will be 120 bits + *gateway_initial_vector size* bits. Counter size should be as big as block size (https://pythonhosted.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CTR)
    block_cipher = AES.new(gateway_private_key,
                           AES.MODE_CTR,
                           counter=ctr_counter)
    derived_key = block_cipher.encrypt(kdf_output)

    # Authentication
    hmac = HMAC.new(kdf_output, digestmod=SHA256)
    hmac.update(anchor_random_number)
    authentication = hmac.hexdigest().encode()[:8]

    # Encryption
    data_frame = anchor_random_number + authentication
    ciphertext = xor(data_frame, derived_key)

    return ciphertext