import argparse
import base64
import binascii
import zlib
import hmac
import hashlib
import struct
from Crypto.Cipher import AES


# obtain values from /usr/local/lib/libfts_license.so.1.12.1
# Note that in python, you enter binary hex values as b"\x0d\x0e..."
HMAC_KEY = b""
HMAC_MSG = b"" * 4
AES_IV = b""


def init_lookup_table():
    out = []
    for i in range(0x100):
        lookup_table_entry = i << 0x18
        for k in range(8):
            if lookup_table_entry >> 31:
                inlr = lookup_table_entry << 1
            if lookup_table_entry >> 31:
                lookup_table_entry = inlr ^ 0x4c11db7
            else:
                lookup_table_entry = lookup_table_entry << 1
            lookup_table_entry &= 0xffffffff
        out.append(lookup_table_entry)
    return out


def spd_crc32(param_1, x):
    tbl = init_lookup_table()
    for pbVar1 in param_1:
        x = (tbl[(pbVar1 ^ x >> 0x18) & 0xff] ^ x << 8) & 0xffffffff
    return x


def simple_generator(ext_features, type, serial):
    if ext_features.lower() == "kvm":
       features = b"\x01\x00\x00\x00"
    elif ext_features.lower() == "kvm_media":
       features = b"\x03\x00\x00\x00"
    elif ext_features.lower() == "kvm_media_elcm":
       # this license type doesn't validate on my TX chassis
       # but apparently works on RX chassis
       if type.lower() == "tx":
           print("License may not be valid for TX chassis with eLCM enabled")
       features = b"\x0f\x00\x00\x00"
    return license_generator(serial, features, type.lower())


def license_generator(serial, features, type):
    # chassis type TX
    struct_data = 0xffffff00
    if type == "rx":
      # chassis type RX
      struct_data = 0xffffff05
    DATA = b'iRMC' \
       + features \
       + struct.pack('>I', struct_data) + \
       struct.pack('<I', spd_crc32(serial.encode("ASCII"), 1))
    print(binascii.hexlify(DATA).decode('utf-8'))

    aes_key = hmac.new(HMAC_KEY, HMAC_MSG, hashlib.sha1).digest()
    # this is AES-128, so only take the first 16 bytes of the aes_key
    cipher = AES.new(aes_key[:16], AES.MODE_CBC, iv=AES_IV)
    encrypted_license = cipher.encrypt(DATA)
    encoded_license = base64.b32encode(encrypted_license)
    license = encoded_license.decode("UTF-8").replace("=","")
    return '-'.join(license[i:i+4] for i in range(0, len(license), 4))


if __name__ == "__main__":
    if len(HMAC_KEY) != 16 or len(HMAC_MSG) != 16*4 or len(AES_IV) != 16:
        print("You are missing the HMAC and AES values")
    else:
        print(simple_generator("kvm_media", "rx", "YV3R002727"))