648 lines
27 KiB
Cython
648 lines
27 KiB
Cython
from libc.string cimport memcpy
|
|
from libc.string cimport strlen
|
|
import random
|
|
|
|
# The sample code contains 10 functions. You will not need to use all these
|
|
# functions in your code. Just use which ever functions are most appropriate
|
|
# and customise in your own way. The sample code is just a guide. You should
|
|
# implement the protection in a stronger way using the techniques described in
|
|
# the "Increasing your Protection" chapter of the manual.
|
|
#
|
|
# If you are using Dinkey Lite then you can only use 4 functions:
|
|
# ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
|
|
|
# this file contains 10 protection-check functions.
|
|
# ProtCheck a standard protection check
|
|
# ProtCheckWithAlg a protection check & executing an Algorithm
|
|
# WriteBytes a protection check & write data to the dongle
|
|
# ReadBytes a protection check & read data from the dongle
|
|
# EncryptUserData a protection check & encrypting data and then decrypting the data
|
|
|
|
# these functions are the same as the functions listed above but encrypting all parameters passed to our API
|
|
# ProtCheckEnc a standard protection check
|
|
# ProtCheckWithAlgEnc a protection check & executing an Algorithm
|
|
# WriteBytesEnc a protection check & write data to the dongle
|
|
# ReadBytesEnc a protection check & read data from the dongle
|
|
# EncryptUserDataEnc a protection check & encrypting data and then decrypting the data
|
|
|
|
DEF MY_SDSN = 10101 # !!!! modify this value to your SDSN
|
|
DEF MY_PRODCODE = b'DEMO' # !!!! change this value to match the Product Code in the dongle
|
|
|
|
# for some reason these constants have to be declared here rather than the pxd file
|
|
# functions - must specify only one
|
|
DEF PROTECTION_CHECK=1 # checks for dongle, check program params...
|
|
DEF EXECUTE_ALGORITHM=2 # protection check + calculate answer for specified algorithm with specified inputs
|
|
DEF WRITE_DATA_AREA=3 # protection check + writes dongle data area
|
|
DEF READ_DATA_AREA=4 # protection check + reads dongle data area
|
|
DEF ENCRYPT_USER_DATA=5 # protection check + the dongle will encrypt user data
|
|
DEF DECRYPT_USER_DATA=6 # protection check + the dongle will decrypt user data
|
|
DEF FAST_PRESENCE_CHECK=7 # checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
|
DEF STOP_NET_USER=8 # stops a network user (a protection check is NOT performed)
|
|
|
|
# flags - can specify as many as you like
|
|
DEF DEC_ONE_EXEC=1 # decrement execs by 1
|
|
DEF DEC_MANY_EXECS=2 # decrement execs by number specified in execs_decrement
|
|
DEF START_NET_USER=4 # starts a network user
|
|
DEF USE_FUNCTION_ARGUMENT=16 # use the extra argument in the function for pointers
|
|
DEF CHECK_LOCAL_FIRST=32 # always look in local ports before looking in network ports
|
|
DEF CHECK_NETWORK_FIRST=64 # always look on the network before looking in local ports
|
|
DEF USE_ALT_PROG_NAME=128 # use name specified in prog_name instead of this program name
|
|
DEF DONT_SET_MAXDAYS_EXPIRY=256 # if the max days expiry date has not been calculated then do not do it this time
|
|
DEF MATCH_DONGLE_NUMBER=512 # restrict the search to match the dongle number specified in the DRIS
|
|
DEF DONT_RETURN_FD_DRIVE=1024 # if an FD dongle has been detected then don't return the flash drive/mount name
|
|
|
|
# ************************* our 10 functions **********************************
|
|
|
|
# ************************** ProtCheck ***************************************
|
|
cpdef int ProtCheck():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = PROTECTION_CHECK # standard protection check
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
# later in your code you can check other values in the DRIS...
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
if (dris.prodcode != MY_PRODCODE):
|
|
print("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
|
|
# ************************** ProtCheckWithAlg ******************************
|
|
|
|
# !!!! You should replace this function with the one generated by the
|
|
# "generate source code" button in Algorithm tab for DinkeyAdd (if you have specified an algorithm)
|
|
# or from DinkeyLook if you are using a Dinkey Lite dongle.
|
|
# (If it does not generate source code for Python you have translate it from C)
|
|
cdef int MyAlgorithm(int a, int b, int c, int d, int e, int f, int g, int h):
|
|
return a + b + c + d + e + f + g + h
|
|
|
|
# NB for this to work you must program at least "user algorithm" into the dongle
|
|
# NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
|
|
# sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample
|
|
# code from DinkeyLook
|
|
cpdef int ProtCheckWithAlg():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = EXECUTE_ALGORITHM # standard protection check and execute algorithm
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.alg_number = 1 # execute algorithm 1 (you do not need to specify this field if you are only using Lite models)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
# if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
|
|
# !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
|
|
if (MyAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h) != dris.alg_answer):
|
|
print("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
|
|
# ************************** WriteBytes ******************************
|
|
# This writes the string "Hello, World!" to the dongle data area at offset 7
|
|
# In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
cpdef int WriteBytes():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
cdef char *datatowrite = "Hello, World!"
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = WRITE_DATA_AREA # standard protection check and write data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.rw_offset = 7
|
|
dris.rw_length = <int>strlen(datatowrite)+1 # include the null
|
|
dris.rw_data_ptr = datatowrite
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
# ************************ ReadBytes ************************************
|
|
# This reads 13 bytes of data from offset 7 in the dongle data area
|
|
# In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
# In order for the data to be displayed properly by this routine it will need to be text data
|
|
cpdef ReadBytes():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
cdef char datatoread[14]
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = READ_DATA_AREA # standard protection check and read data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.rw_offset = 7
|
|
dris.rw_length = sizeof(datatoread)
|
|
dris.rw_data_ptr = datatoread
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
print("It worked! Dinkey Dongle Data area, offset 7 is: " + str(datatoread))
|
|
return 0
|
|
|
|
# ************************** EncryptUserData ****************************
|
|
# This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
|
# It will then do another protection check & decrypt the data
|
|
cpdef EncryptUserData():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
cdef char *mydata = "Hello, World!"
|
|
cdef int data_length = <int>strlen(mydata)+1 # include the NULL
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = ENCRYPT_USER_DATA # standard protection check and encrypt data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.data_crypt_key_num = 1
|
|
dris.rw_length = data_length
|
|
dris.rw_data_ptr = mydata
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
# ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
|
|
|
# Now decrypt this (encrypted) data to get the original values
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = DECRYPT_USER_DATA # standard protection check and decrypt data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.data_crypt_key_num = 1
|
|
dris.rw_length = data_length
|
|
dris.rw_data_ptr = mydata
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
print("It worked! Data decrypted is " + str(mydata))
|
|
return 0
|
|
|
|
# !!!!!!!!!!! all the functions listed below encrypt all parameters to our API !!!!!!!!!!!!!!!!!!!!!
|
|
# In order for them to work properly you need to choose "Encrypt DRIS" and "Encrypt Data passed to API"
|
|
# in the Extra Security tab of DinkeyAdd. In this example, for Data Encryption I use the r/w algorithm
|
|
# but the code can be modified easily to use the 3 encryption parameters.
|
|
|
|
# !!!! please overwrite this function with the one generated by DinkeyAdd for R/W Algorithm
|
|
# NB DinkeyAdd currently does not generate code for Python so you will have to translate it from C
|
|
cdef int MyRWAlgorithm(int a, int b, int c, int d, int e, int f, int g, int h):
|
|
return a ^ b ^ c ^ d ^ e ^ f
|
|
|
|
# !!!! modify parameters 1,2 and 3 to match those specified in DinkeyAdd
|
|
cdef void CryptDRIS(DRIS *dris, unsigned int seed1, unsigned int seed2):
|
|
cdef int i, j, k, t
|
|
cdef unsigned char bigseed[256]
|
|
cdef unsigned char S[256]
|
|
cdef unsigned char temp
|
|
|
|
for i in range(0, 256, 8):
|
|
memcpy(bigseed+i, &seed1, 4)
|
|
memcpy(bigseed+i+4, &seed2, 4)
|
|
for i in range(256):
|
|
S[i] = i
|
|
j = 0
|
|
for i in range(256):
|
|
j = (j + S[i] + bigseed[i] + 123) % 256 # parameter 1
|
|
temp = S[i]
|
|
S[i] = S[j]
|
|
S[j] = temp
|
|
i = 0
|
|
j = 0
|
|
for k in range(16, <int>sizeof(DRIS)):
|
|
i = (i + 1) % 256
|
|
j = (j + S[i] + 212) % 256 # parameter 2
|
|
temp = S[i]
|
|
S[i] = S[j]
|
|
S[j] = temp
|
|
t = (S[i] + S[j] + 97) % 256 # parameter 3
|
|
(<unsigned char *>dris)[k] ^= S[t]
|
|
return
|
|
|
|
# !!!! modify parameters 1,2 and 3 to match those specified in DinkeyAdd (if you specified r/w algorithm then no need to modify anything)
|
|
cdef void CryptApiData(unsigned char *mydata, int length, unsigned int seed1, unsigned int seed2, int alg_answer):
|
|
cdef int i, j, k, t
|
|
cdef unsigned char bigseed[256]
|
|
cdef unsigned char S[256]
|
|
cdef unsigned char temp
|
|
|
|
for i in range(0, 256, 8):
|
|
memcpy(bigseed+i, &seed1, 4)
|
|
memcpy(bigseed+i+4, &seed2, 4)
|
|
for i in range(256):
|
|
S[i] = i
|
|
j = 0
|
|
for i in range(256):
|
|
j = (j + S[i] + bigseed[i] + (alg_answer & 0xff)) % 256 # parameter1
|
|
temp = S[i]
|
|
S[i] = S[j]
|
|
S[j] = temp
|
|
i = 0
|
|
j = 0
|
|
for k in range(length):
|
|
i = (i + 1) % 256
|
|
j = (j + S[i] + ((alg_answer >> 8) & 0xff)) % 256 # parameter 2
|
|
temp = S[i]
|
|
S[i] = S[j]
|
|
S[j] = temp
|
|
t = (S[i] + S[j] + ((alg_answer >> 16) & 0xff)) % 256 # parameter 3
|
|
(<unsigned char *>mydata)[k] ^= S[t]
|
|
return
|
|
|
|
# ************************** ProtCheckEnc ***************************************
|
|
# We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file with parameters specified in DinkeyAdd
|
|
# NB if you are using the debug module then do not call CryptDRIS as DRIS encryption is not supported. See notes in C readme.txt
|
|
cpdef int ProtCheckEnc():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = PROTECTION_CHECK # standard protection check
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
# later in your code you can check other values in the DRIS...
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
if (dris.prodcode != MY_PRODCODE):
|
|
print("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
|
|
# ************************** ProtCheckWithAlgEnc ******************************
|
|
|
|
# NB for this to work you must program at least "user algorithm" into the dongle
|
|
# NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
|
|
# sample code generated by DinkeyAdd for the algorithm that you are using. For Lite models copy the sample
|
|
# code from DinkeyLook
|
|
# We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file with parameters specified in DinkeyAdd
|
|
cpdef int ProtCheckWithAlgEnc():
|
|
cdef DRIS dris
|
|
cdef int ret_code
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = EXECUTE_ALGORITHM # standard protection check and execute algorithm
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.alg_number = 1 # execute algorithm 1 (you do not need to specify this field if you are only using Lite models)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
# if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
|
|
# !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
|
|
if (MyAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h) != dris.alg_answer):
|
|
print("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
|
|
# ************************** WriteBytesEnc ******************************
|
|
# This writes the string "Hello, World!" to the dongle data area at offset 7
|
|
# In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
# We encrypt the DRIS and Data passed to the API. Patch the CryptDRIS and CryptApiData functions in this file with parameters specified in DinkeyAdd.
|
|
cpdef int WriteBytesEnc():
|
|
cdef DRIS dris
|
|
cdef int ret_code, alg_answer
|
|
cdef char *datatowrite = "Hello, World!"
|
|
cdef string_length = <int>strlen(datatowrite)+1 # include the null
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = WRITE_DATA_AREA # standard protection check and write data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.rw_offset = 7
|
|
dris.rw_length = string_length
|
|
dris.rw_data_ptr = datatowrite
|
|
|
|
# calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm specified in DinkeyAdd
|
|
alg_answer = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
|
|
|
|
# encrypt data we want to write.
|
|
CryptApiData(<unsigned char *>datatowrite, string_length, dris.seed1, dris.seed2, alg_answer)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
print("It worked!")
|
|
return 0
|
|
|
|
# ************************ ReadBytesEnc ************************************
|
|
# This reads 13 bytes of data from offset 7 in the dongle data area
|
|
# In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
|
# In order for the data to be displayed properly by this routine it will need to be text data
|
|
# We encrypt the DRIS and Data passed to the API. Patch the CryptDRIS and CryptApiData functions in this file with parameters specified in DinkeyAdd.
|
|
cpdef ReadBytesEnc():
|
|
cdef DRIS dris
|
|
cdef int ret_code, alg_answer
|
|
cdef char datatoread[14]
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = READ_DATA_AREA # standard protection check and read data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.rw_offset = 7
|
|
dris.rw_length = sizeof(datatoread)
|
|
dris.rw_data_ptr = datatoread
|
|
|
|
# calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm specified in DinkeyAdd
|
|
alg_answer = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
if (dris.sdsn != MY_SDSN):
|
|
print("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
|
|
return -1
|
|
|
|
# later on in your program you can check the return code again
|
|
if (dris.ret_code != 0):
|
|
print("Dinkey Dongle protection error")
|
|
return -1
|
|
|
|
# decrypt data that was read
|
|
CryptApiData(<unsigned char *>datatoread, sizeof(datatoread), dris.seed1, dris.seed2, alg_answer)
|
|
|
|
print("It worked! Dinkey Dongle Data area, offset 7 is: " + str(datatoread))
|
|
return 0
|
|
|
|
# ************************** EncryptUserDataEnc ****************************
|
|
# This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
|
# It will then do another protection check & decrypt the data
|
|
# We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
|
cpdef EncryptUserDataEnc():
|
|
cdef DRIS dris
|
|
cdef int ret_code, alg_answer
|
|
cdef char *mydata = "Hello, World!"
|
|
cdef int data_length = <int>strlen(mydata)+1 # include the NULL
|
|
|
|
# set the DRIS to have random values
|
|
cdef unsigned char *drisbuf = <unsigned char*>&dris
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
# then set the values we want to use
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = ENCRYPT_USER_DATA # standard protection check and encrypt data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.data_crypt_key_num = 1
|
|
dris.rw_length = data_length
|
|
dris.rw_data_ptr = mydata
|
|
|
|
# calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm specified in DinkeyAdd
|
|
alg_answer = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
|
|
|
|
# encrypt data we want to write.
|
|
CryptApiData(<unsigned char *>mydata, data_length, dris.seed1, dris.seed2, alg_answer)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
# ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
|
|
|
# Now decrypt this (encrypted) data to get the original values
|
|
for i in range(sizeof(DRIS)):
|
|
drisbuf[i]= <unsigned char>random.randint(0,255)
|
|
memcpy(dris.header, b'DRIS', 4)
|
|
dris.size = sizeof(DRIS)
|
|
dris.function = DECRYPT_USER_DATA # standard protection check and decrypt data
|
|
dris.flags = 0 # no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
dris.data_crypt_key_num = 1
|
|
dris.rw_length = data_length
|
|
dris.rw_data_ptr = mydata
|
|
|
|
# calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm specified in DinkeyAdd
|
|
alg_answer = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(&dris, NULL)
|
|
|
|
CryptDRIS(&dris, dris.seed1, dris.seed2) # decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
if (ret_code != 0):
|
|
DisplayError(ret_code, dris.ext_err)
|
|
return ret_code
|
|
|
|
# decrypt data that was pass to us by the API
|
|
CryptApiData(<unsigned char *>mydata, data_length, dris.seed1, dris.seed2, alg_answer)
|
|
|
|
print("It worked! Data decrypted is " + str(mydata))
|
|
return 0
|
|
|
|
|
|
#displays messages for the most common errors. You will want to change this for your code
|
|
cdef void DisplayError(int ret_code, int extended_error):
|
|
cdef char szBuffer[200]
|
|
|
|
if (ret_code == 401):
|
|
print("Error! No dongles detected!")
|
|
elif (ret_code == 403):
|
|
print("Error! The dongle detected has a different type to the one specified in DinkeyAdd.")
|
|
elif (ret_code == 404):
|
|
print("Error! The dongle detected has a different model to those specified in DinkeyAdd.")
|
|
elif (ret_code == 409):
|
|
print("Error! The dongle detected has not been programmed by DinkeyAdd.")
|
|
elif (ret_code == 410):
|
|
print("Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd.")
|
|
elif (ret_code == 411):
|
|
print("Error! The dongle detected does not contain the licence associated with this program.")
|
|
elif (ret_code == 413):
|
|
print("Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual.")
|
|
elif (ret_code == 417):
|
|
print("Error! One or more of the parameters set in the DRIS is incorrect. This could be caused if you are encrypting the DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa.")
|
|
elif (ret_code == 423):
|
|
print("Error! The number of network users has been exceeded.")
|
|
elif (ret_code == 435):
|
|
print("Error! DinkeyServer has not been detected on the network.")
|
|
elif (ret_code == 922):
|
|
print("Error! The Software Key has expired.")
|
|
else:
|
|
print("An error occurred checking the dongle.\nError: " + str(ret_code) + ", Extended Error: " + str(extended_error))
|
|
return
|