#!/usr/bin/python

import os

from ctypes import *
from array import array

# OEM Private Data Key

RANDOM_LEN_A = 6
RANDOM_LEN_B = 11
RANDOM_LEN_C = 5
RANDOM_LEN_D = 12
OEM_KEY_LEN  = 24

# OEM Private API

TOTAL_BUF_LEN                        = 1024

GET_ESTABLISH_DATA                   = 0
ESTABLISH_CONNECTION                 = 1
ALLOWED_DEVICE_CONNECTIONS_ON_SERVER = 3
ALLOWED_DEVICECONNECTIONS_ON_CLIENT  = 5

class USBRDRPRIVATE(Structure):
    _fields_ = [
        ("random_a", c_ubyte * RANDOM_LEN_A),
        ("key_offset", c_ubyte),
        ("random_b", c_ubyte * RANDOM_LEN_B),
        ("step", c_ubyte),
        ("random_c", c_ubyte * RANDOM_LEN_C),
        ("mul_offset", c_ubyte),
        ("random_d", c_ubyte * RANDOM_LEN_D),
        ("div_offset", c_ubyte)
    ]

# OEM Private Data Key

OEM_KEY = ( 0x53, 0xa7, 0x11, 0xd0, 0x2b, 0xdc, 0x73, 0x75, 0xcc, 0xa6, 0x16, 0x5f, 0x58, 0x1e, 0x3b, 0x23, 0x5f, 0xe4, 0x3a, 0x6f, 0xc7, 0x1d, 0xe4, 0xdd )

def DoUsbAuthorization():

    if cdll.spiceusbapi.InitUsbRedirectorApi():

        data_in = os.urandom(TOTAL_BUF_LEN)
        data_out = array('B', os.urandom(TOTAL_BUF_LEN))

        if cdll.spiceusbapi.UsbRedirectorServiceCall(GET_ESTABLISH_DATA, data_in, TOTAL_BUF_LEN):
            usb_private = cast(data_in, POINTER(USBRDRPRIVATE)).contents

            # Convert from 'str' to array of bytes in order to allow shifting operand.
            data_in = array('B', data_in)

            data_out[usb_private.mul_offset] = (data_in[usb_private.mul_offset] << 1) & 0xff
            data_out[usb_private.div_offset] = data_in[usb_private.div_offset] >> 1

            for i  in range(OEM_KEY_LEN):
                data_out[usb_private.key_offset + (i * usb_private.step)] = data_in[usb_private.key_offset + (i * usb_private.step)] ^ OEM_KEY[i]

            if cdll.spiceusbapi.UsbRedirectorServiceCall(ESTABLISH_CONNECTION, data_out.tostring(), TOTAL_BUF_LEN):
                # Allow using up to 20 devices on the client.
                cdll.spiceusbapi.UsbRedirectorServiceCall(ALLOWED_DEVICECONNECTIONS_ON_CLIENT, byref(c_long(20)), 4)

        cdll.spiceusbapi.DeInitUsbRedirectorApi()

if __name__ == '__main__':
    DoUsbAuthorization()
