Atmosphere/sept/sept-secondary/sept_sign.py

79 lines
2.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python
import sys
from struct import pack as pk, unpack as up
from Crypto.Cipher import AES
from Crypto.Hash import CMAC
try:
import KEYS
except ImportError:
import KEYS_template as KEYS
print('Warning: output will not work on 7.0.0+!')
2019-02-21 16:52:42 +01:00
2019-02-20 15:54:44 +01:00
def shift_left_xor_rb(s):
2019-02-21 16:52:42 +01:00
if hasattr(int, "from_bytes"):
N = int.from_bytes(s, byteorder="big")
else:
N = int(s.encode('hex'), 16)
2019-02-20 15:54:44 +01:00
if N & (1 << 127):
N = ((N << 1) ^ 0x87) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
else:
N = ((N << 1) ^ 0x00) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
2019-02-21 16:52:42 +01:00
return bytearray.fromhex('%032x' % N)
2019-02-20 15:54:44 +01:00
def sxor(x, y):
2019-02-21 16:52:42 +01:00
return bytearray(a^b for a,b in zip(x, y))
2019-02-20 15:54:44 +01:00
def get_last_block_for_desired_mac(key, data, desired_mac):
assert len(desired_mac) == 0x10
2019-02-21 16:52:42 +01:00
k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt(bytearray(0x10)))
2019-02-20 15:54:44 +01:00
if len(data) & 0xF:
k1 = shift_left_xor_rb(k1)
2019-02-21 16:52:42 +01:00
data += b'\x80'
data += bytearray((0x10 - (len(data) & 0xF)) & 0xF)
2019-02-20 15:54:44 +01:00
num_blocks = (len(data) + 0xF) >> 4
2019-02-21 16:52:42 +01:00
last_block = sxor(bytearray(AES.new(key, AES.MODE_ECB).decrypt(desired_mac)), bytearray(k1))
2019-02-20 15:54:44 +01:00
if len(data) > 0x0:
2019-02-21 16:52:42 +01:00
last_block = sxor(last_block, bytearray(AES.new(key, AES.MODE_CBC, bytearray(0x10)).encrypt(data)[-0x10:]))
2019-02-20 15:54:44 +01:00
return last_block
2019-02-21 16:52:42 +01:00
2019-02-20 15:54:44 +01:00
def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac):
# Pad with 0x20 of zeroes.
2019-02-21 16:52:42 +01:00
code += bytearray(0x20)
code_len = len(code)
code_len += 0xFFF
code_len &= ~0xFFF
2019-02-21 16:52:42 +01:00
code += bytearray(code_len - len(code))
# Add empty trustzone, warmboot segments.
2019-02-21 16:52:42 +01:00
code += bytearray(0x1FE0 - 0x10)
pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0)
pk11 = pk11_hdr + code
enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11)
2019-02-20 15:54:44 +01:00
enc_pk11 = pk('<IIII', len(pk11) + 0x10, 0, 0, 0) + iv + enc_pk11
enc_pk11 += get_last_block_for_desired_mac(sig_key, enc_pk11, desired_mac)
enc_pk11 += CMAC.new(sig_key, enc_pk11, AES).digest()
return enc_pk11
2019-02-21 16:52:42 +01:00
def main(argc, argv):
if argc != 3:
print('Usage: %s input output' % argv[0])
return 1
with open(argv[1], 'rb') as f:
code = f.read()
if len(code) & 0xF:
2019-02-21 16:52:42 +01:00
code += bytearray(0x10 - (len(code) & 0xF))
# TODO: Support dev unit crypto
with open(argv[2], 'wb') as f:
2019-02-21 16:52:42 +01:00
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, b'THANKS_NVIDIA_<3'))
return 0
2019-02-21 16:52:42 +01:00
if __name__ == '__main__':
2019-02-21 16:25:42 +01:00
sys.exit(main(len(sys.argv), sys.argv))