930 lines
32 KiB
Plaintext
930 lines
32 KiB
Plaintext
* Sample code for Visual Foxpro
|
|
* Compiled and tested with Microsoft Visual Foxpro 6.0
|
|
SET TALK On
|
|
CLEAR DLLS
|
|
|
|
* declare functions in Dinkey Pro module dpwin32.dll
|
|
Declare INTEGER DDProtCheck IN "dpwin32.dll" STRING @dris, STRING @data
|
|
|
|
* 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.
|
|
*
|
|
* Sample Code Functions:
|
|
* ProtCheck, ProtCheckWithAlg, WriteBytes, ReadBytes, EncryptUserData
|
|
*
|
|
* and also these functions but encrypting all parameters passed to our API:
|
|
* ProtCheckEnc, ProtCheckWithAlgEnc, WriteBytesEnc, ReadBytesEnc, EncryptUserDataEnc
|
|
*
|
|
* If you are using Dinkey Lite then you can only use 4 functions:
|
|
* ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
|
*
|
|
|
|
#define MY_SDSN 10101 && !!!! change this value to be the value of your SDSN (demo = 10101)
|
|
#define MY_PRODCODE "DEMO" && !!!! change this value to match the Product Code in the dongle
|
|
|
|
#define DRIS_SIZE 560
|
|
|
|
* functions constants - must specify only one
|
|
#define PROTECTION_CHECK 1 && checks for dongle, check program params...
|
|
#define EXECUTE_ALGORITHM 2 && protection check + calculate answer for specified algorithm with specified inputs
|
|
#define WRITE_DATA_AREA 3 && protection check + writes dongle data area
|
|
#define READ_DATA_AREA 4 && protection check + reads dongle data area
|
|
#define ENCRYPT_USER_DATA 5 && protection check + the dongle will encrypt user data
|
|
#define DECRYPT_USER_DATA 6 && protection check + the dongle will decrypt user data
|
|
#define FAST_PRESENCE_CHECK 7 && checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
|
#define STOP_NET_USER 8 && stops a network user (a protection check is NOT performed)
|
|
|
|
* flags constants - can specify as many as you like
|
|
#define DEC_ONE_EXEC 1 && decrement execs by 1
|
|
#define DEC_MANY_EXECS 2 && decrement execs by number specified in execs_decrement
|
|
#define START_NET_USER 4 && starts a network user
|
|
#define USE_FUNCTION_ARGUMENT 16 && use the extra argument in the function for pointers
|
|
#define CHECK_LOCAL_FIRST 32 && always look in local ports before looking in network ports
|
|
#define CHECK_NETWORK_FIRST 64 && always look on the network before looking in local ports
|
|
#define USE_ALT_LICENCE_NAME 128 && use name specified in alt_licence_name instead of the default one
|
|
#define DONT_SET_MAXDAYS_EXPIRY 256 && if the max days expiry date has not been calculated then do not do it this time
|
|
#define MATCH_DONGLE_NUMBER 512 && restrict the search to match the dongle number specified in the DRIS
|
|
#define DONT_RETURN_FD_DRIVE 1024 && if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
|
|
|
********************** entry point *******************************
|
|
* call the function of your choice:
|
|
|
|
IF ProtCheck() == 0
|
|
? "It Worked!"
|
|
ELSE
|
|
&& QUIT && you would probably want to QUIT if the protection check failed. We don't do that here so you can see display error messages
|
|
ENDIF
|
|
|
|
clear dlls
|
|
|
|
|
|
********************* protection check functions *******************
|
|
*** ProtCheck
|
|
FUNCTION ProtCheck
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, PROTECTION_CHECK) && standard protection check
|
|
SetDrisFlags(@dris, 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(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
IF GetDrisProdCode(dris) != MY_PRODCODE
|
|
? "Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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. You will have to translate this from another language e.g. C
|
|
FUNCTION MyAlgorithm(a, b, c, d, e, f, g, h)
|
|
RETURN a + b + c + d + e + f + g + h
|
|
ENDFUNC
|
|
|
|
* 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
|
|
FUNCTION ProtCheckWithAlg
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, EXECUTE_ALGORITHM) && standard protection check & execute specified algorithm
|
|
SetDrisFlags(@dris, 0) && no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
SetDrisAlgNumber(@dris, 1) && execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
|
&& set variables for algorithm
|
|
SetDrisAlgVars(@dris, 1, 2, 3, 4 , 5, 6, 7, 8) && you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
|
|
|
ret_code = DDProtCheck(@dris, NULL)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* 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(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), ;
|
|
GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris)) != GetDrisAlgAnswer(dris)
|
|
? "Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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.
|
|
FUNCTION WriteBytes
|
|
DataToWrite = "Hello, World!"
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, WRITE_DATA_AREA) && standard protection check and write the dongle data area
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to write as an extra parameter to DDProtCheck
|
|
SetDrisRWOffset(@dris, 7)
|
|
SetDrisRWLength(@dris, LEN(DataToWrite))
|
|
|
|
ret_code = DDProtCheck(@dris, @DataToWrite)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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
|
|
FUNCTION ReadBytes
|
|
DataRead = "Data Read goes here" && we must initialise this to something that is at least as long as the data we are reading
|
|
data_length = 13
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, READ_DATA_AREA) && standard protection check and read the dongle data area
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to read as an extra parameter to DDProtCheck
|
|
SetDrisRWOffset(@dris, 7)
|
|
SetDrisRWLength(@dris, data_length)
|
|
|
|
ret_code = DDProtCheck(@dris, @DataRead)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
DataRead = SUBSTR(DataRead, 1, data_length) && shorten string so it just contains the data read
|
|
? "Dinkey Dongle Data area, offset 7 is: " + DataRead
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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
|
|
FUNCTION EncryptUserData
|
|
MyData = "Hello, World!" && this is the data that we are going to encrypt
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, ENCRYPT_USER_DATA) && standard protection check and encrypt data
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to encrypt as an extra parameter to DDProtCheck
|
|
SetDrisDataCryptKeyNum(@dris, 1)
|
|
SetDrisRWLength(@dris, Len(MyData))
|
|
|
|
ret_code = DDProtCheck(@dris, @MyData)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
|
|
|
* Now decrypt this encrypted data to get the original
|
|
dris = random_dris()
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, DECRYPT_USER_DATA) && standard protection check and decrypt data
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to encrypt as an extra parameter to DDProtCheck
|
|
SetDrisDataCryptKeyNum(@dris, 1)
|
|
SetDrisRWLength(@dris, Len(MyData))
|
|
|
|
ret_code = DDProtCheck(@dris, @MyData)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
? "Decrypted data is: " + MyData
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
* !!!!!!!!!!! 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
|
|
* in this case you will have to translate from C or another programming language
|
|
FUNCTION MyRWAlgorithm(a, b, c, d, e, f, g, h)
|
|
RETURN BITXOR(BITXOR(BITXOR(BITXOR(BITXOR(a, b), c), d), e), f)
|
|
ENDFUNC
|
|
|
|
* !!!! please overwrite this function with the one generated by DinkeyAdd
|
|
* in this case you will have to just patch the parameter values in the code
|
|
FUNCTION CryptDRIS(mydris, seed1, seed2)
|
|
DECLARE bigseed[256] As Integer
|
|
DECLARE S[256] As Integer
|
|
|
|
FOR i=1 TO 256 STEP 8
|
|
SETARRAY4BYTES(@bigseed, i, seed1)
|
|
SETARRAY4BYTES(@bigseed, i+4, seed2)
|
|
ENDFOR
|
|
|
|
FOR i=1 TO 256
|
|
S[i] = i-1
|
|
ENDFOR
|
|
|
|
j = 0
|
|
FOR i = 0 TO 255
|
|
j = BITAND(j + S[i+1]+ bigseed[i+1] + 123, 255) && parameter 1 is 123
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
ENDFOR
|
|
|
|
i = 0
|
|
j = 0
|
|
FOR k=17 TO DRIS_SIZE
|
|
i = BITAND(i + 1, 255)
|
|
j = BITAND(j + S[i+1] + 212, 255) && parameter 2 is 212
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
t = BITAND(S[i+1] + S[j+1] + 97, 255) && parameter 3 is 97
|
|
temp = ASC(SUBSTR(mydris, k, 1))
|
|
mydris = STUFF(mydris, k, 1, CHR(BITXOR(temp,S[t+1])))
|
|
ENDFOR
|
|
ENDFUNC
|
|
|
|
* !!!! please overwrite this function with the one generated by DinkeyAdd
|
|
* in this case you will have to just patch the parameter values in the code
|
|
FUNCTION CryptApiData(mydata, length, seed1, seed2, alg_answer)
|
|
DECLARE bigseed[256] As Integer
|
|
DECLARE S[256] As Integer
|
|
|
|
FOR i=1 TO 256 STEP 8
|
|
SETARRAY4BYTES(@bigseed, i, seed1)
|
|
SETARRAY4BYTES(@bigseed, i+4, seed2)
|
|
ENDFOR
|
|
|
|
FOR i=1 TO 256
|
|
S[i] = i-1
|
|
ENDFOR
|
|
|
|
j = 0
|
|
FOR i = 0 TO 255
|
|
j = BITAND(j + S[i+1]+ bigseed[i+1] + BITAND(alg_answer, 255), 255) && parameter 1
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
ENDFOR
|
|
|
|
i = 0
|
|
j = 0
|
|
FOR k=1 TO length
|
|
i = BITAND(i + 1, 255)
|
|
j = BITAND(j + S[i+1] + BITAND(BITRSHIFT(alg_answer, 8),255), 255) && parameter 2
|
|
temp = S[i+1]
|
|
S[i+1] = S[j+1]
|
|
S[j+1] = temp
|
|
t = BITAND(S[i+1] + S[j+1] + BITAND(BITRSHIFT(alg_answer, 16),255), 255) && parameter 3
|
|
temp = ASC(SUBSTR(mydata, k, 1))
|
|
mydata = STUFF(mydata, k, 1, CHR(BITXOR(temp,S[t+1])))
|
|
ENDFOR
|
|
ENDFUNC
|
|
|
|
*** ProtCheckEnc
|
|
* We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
|
FUNCTION ProtCheckEnc
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, PROTECTION_CHECK) && standard protection check
|
|
SetDrisFlags(@dris, 0) && no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, NULL)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
IF GetDrisProdCode(dris) != MY_PRODCODE
|
|
? "Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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 from source code generated by DinkeyAdd.
|
|
FUNCTION ProtCheckWithAlgEnc
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, EXECUTE_ALGORITHM) && standard protection check & execute specified algorithm
|
|
SetDrisFlags(@dris, 0) && no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
|
SetDrisAlgNumber(@dris, 1) && execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
|
&& set variables for algorithm
|
|
SetDrisAlgVars(@dris, 1, 2, 3, 4 , 5, 6, 7, 8) && you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, NULL)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* 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(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), ;
|
|
GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris)) != GetDrisAlgAnswer(dris)
|
|
? "Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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.
|
|
* We encrypt the DRIS and Data passed to the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
|
FUNCTION WriteBytesEnc
|
|
DataToWrite = "Hello, World!"
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, WRITE_DATA_AREA) && standard protection check and write the dongle data area
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to write as an extra parameter to DDProtCheck
|
|
SetDrisRWOffset(@dris, 7)
|
|
SetDrisRWLength(@dris, LEN(DataToWrite))
|
|
|
|
* calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
|
alg_ans = MyRWAlgorithm(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris))
|
|
|
|
* encrypt data we want to write.
|
|
CryptApiData(@DataToWrite, LEN(DataToWrite), GetDrisSeed1(dris), GetDrisSeed2(dris), alg_ans)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, @DataToWrite)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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
|
|
FUNCTION ReadBytesEnc
|
|
DataRead = "Data Read goes here" && we must initialise this to something that is at least as long as the data we are reading
|
|
data_length = 13
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, READ_DATA_AREA) && standard protection check and read the dongle data area
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to read as an extra parameter to DDProtCheck
|
|
SetDrisRWOffset(@dris, 7)
|
|
SetDrisRWLength(@dris, data_length)
|
|
|
|
* calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
|
alg_ans = MyRWAlgorithm(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris))
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, @DataRead)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* decrypt data we read
|
|
CryptApiData(@DataRead, data_length, GetDrisSeed1(dris), GetDrisSeed2(dris), alg_ans)
|
|
DataRead = SUBSTR(DataRead, 1, data_length) && shorten string so it just contains the data read
|
|
? "Dinkey Dongle Data area, offset 7 is: " + DataRead
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
*** 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
|
|
FUNCTION EncryptUserDataEnc
|
|
MyData = "Hello, World!" && this is the data that we are going to encrypt
|
|
|
|
* create & initialise DRIS to random values & set header
|
|
dris = random_dris()
|
|
|
|
* set DRIS values to be what we want to use
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, ENCRYPT_USER_DATA) && standard protection check and encrypt data
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to encrypt as an extra parameter to DDProtCheck
|
|
SetDrisDataCryptKeyNum(@dris, 1)
|
|
SetDrisRWLength(@dris, Len(MyData))
|
|
|
|
* calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
|
alg_ans = MyRWAlgorithm(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris))
|
|
|
|
* encrypt data we want to pass.
|
|
CryptApiData(@MyData, LEN(MyData), GetDrisSeed1(dris), GetDrisSeed2(dris), alg_ans)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, @MyData)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
|
|
|
* Now decrypt this encrypted data to get the original
|
|
dris = random_dris()
|
|
SetDrisSize(@dris)
|
|
SetDrisFunction(@dris, DECRYPT_USER_DATA) && standard protection check and decrypt data
|
|
SetDrisFlags(@dris, USE_FUNCTION_ARGUMENT) && we need to set this as we are passing the data to encrypt as an extra parameter to DDProtCheck
|
|
SetDrisDataCryptKeyNum(@dris, 1)
|
|
SetDrisRWLength(@dris, Len(MyData))
|
|
|
|
* calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
|
alg_ans = MyRWAlgorithm(GetDrisVarA(dris), GetDrisVarB(dris), GetDrisVarC(dris), GetDrisVarD(dris), GetDrisVarE(dris), GetDrisVarF(dris), GetDrisVarG(dris), GetDrisVarH(dris))
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
ret_code = DDProtCheck(@dris, @MyData)
|
|
|
|
CryptDRIS(@dris, GetDrisSeed1(dris), GetDrisSeed2(dris)) && decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
|
|
|
IF ret_code != 0
|
|
DisplayError(dris, ret_code)
|
|
RETURN ret_code
|
|
ENDIF
|
|
|
|
* later in your code you can check other values in the DRIS...
|
|
IF GetDrisSDSN(dris) != MY_SDSN
|
|
? "Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* later on in your program you can check the return code again
|
|
IF GetDrisRetCode(@dris) != 0
|
|
? "Dinkey Dongle protection error"
|
|
RETURN -1
|
|
ENDIF
|
|
|
|
* decrypt data passed to us by API
|
|
CryptApiData(@MyData, Len(MyData), GetDrisSeed1(dris), GetDrisSeed2(dris), alg_ans)
|
|
? "Decrypted data is: " + MyData
|
|
|
|
* It worked!
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
|
|
|
|
******************************** useful functions *********************************
|
|
|
|
* this function extract a 4-byte numeric field from the dris
|
|
FUNCTION GET4BYTES(mydris, offset)
|
|
value1 = ASC(SUBSTR(mydris, offset + 3)) * 16777216 + ;
|
|
ASC(SUBSTR(mydris, offset + 2)) * 65536 + ;
|
|
ASC(SUBSTR(mydris, offset + 1)) * 256 + ;
|
|
ASC(SUBSTR(mydris, offset))
|
|
RETURN value1
|
|
ENDFUNC
|
|
|
|
* this function sets a 4-byte numeric field in the dris, you should pass dris by reference
|
|
FUNCTION SET4BYTES(mydris, offset, value1)
|
|
string_value = CHR(BITAND(value1, 255)) + CHR(BITAND(BITRSHIFT(value1, 8),255)) + CHR(BITAND(BITRSHIFT(value1, 16),255)) + CHR(BITAND(BITRSHIFT(value1, 24),255))
|
|
mydris = STUFF(mydris, offset, 4, string_value)
|
|
ENDFUNC
|
|
|
|
* this does the same thing but for an array
|
|
FUNCTION SETARRAY4BYTES(myArray, offset, value1)
|
|
myArray[offset] = BITAND(value1, 255)
|
|
myArray[offset+1] = BITAND(BITRSHIFT(value1, 8),255)
|
|
myArray[offset+2] = BITAND(BITRSHIFT(value1, 16),255)
|
|
myArray[offset+3] = BITAND(BITRSHIFT(value1, 24),255)
|
|
ENDFUNC
|
|
|
|
* this function will initialise the DRIS to random values and set the first four bytes to 'DRIS'
|
|
FUNCTION random_dris
|
|
RAND(-1) && seeds using time
|
|
dris = "DRIS"
|
|
FOR i = 5 TO DRIS_SIZE
|
|
dris = dris + CHR(RAND() * 255)
|
|
ENDFOR
|
|
RETURN dris
|
|
ENDFUNC
|
|
|
|
*** these functions let you set values in the DRIS (NB offsets are 1-based)
|
|
* NB you should pass dris by reference when you call these functions. e.g. SetDrisSize(@dris)
|
|
FUNCTION SetDrisSize(mydris)
|
|
SET4BYTES(@mydris, 5, DRIS_SIZE)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisFunction(mydris, myfunction)
|
|
SET4BYTES(@mydris, 17, myfunction)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisFlags(mydris, myflags)
|
|
SET4BYTES(@mydris, 21, myflags)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisExecsDecrement(mydris, myexecs)
|
|
SET4BYTES(@mydris, 25, myexecs)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisDataCryptKeyNum(mydris, mykey)
|
|
SET4BYTES(@mydris, 29, mykey)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisRWOffset(mydris, myoffset)
|
|
SET4BYTES(@mydris, 33, myoffset)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisRWLength(mydris, mylength)
|
|
SET4BYTES(@mydris, 37, mylength)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisAltLicenceName(mydris, alt_licence_name)
|
|
alt_licence_name = alt_licence_name + Chr(0) && null-terminate this string
|
|
mydris = STUFF(mydris, 45, 256, alt_licence_name)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisAlgVars(mydris, var_a, var_b, var_c, var_d, var_e, var_f, var_g, var_h)
|
|
SET4BYTES(@mydris, 301, var_a)
|
|
SET4BYTES(@mydris, 305, var_b)
|
|
SET4BYTES(@mydris, 309, var_c)
|
|
SET4BYTES(@mydris, 313, var_d)
|
|
SET4BYTES(@mydris, 317, var_e)
|
|
SET4BYTES(@mydris, 321, var_f)
|
|
SET4BYTES(@mydris, 325, var_g)
|
|
SET4BYTES(@mydris, 329, var_h)
|
|
ENDFUNC
|
|
|
|
FUNCTION SetDrisAlgNumber(mydris, alg_num)
|
|
SET4BYTES(@mydris, 333, alg_num)
|
|
ENDFUNC
|
|
|
|
*** these functions let you get values from the DRIS (NB offsets are 1-based)
|
|
FUNCTION GetDrisVarA(mydris) && you may want to use these functions if you set dris vars to be random
|
|
RETURN GET4BYTES(mydris, 301)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarB(mydris)
|
|
RETURN GET4BYTES(mydris, 305)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarC(mydris)
|
|
RETURN GET4BYTES(mydris, 309)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarD(mydris)
|
|
RETURN GET4BYTES(mydris, 313)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarE(mydris)
|
|
RETURN GET4BYTES(mydris, 317)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarF(mydris)
|
|
RETURN GET4BYTES(mydris, 321)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarG(mydris)
|
|
RETURN GET4BYTES(mydris, 325)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisVarH(mydris)
|
|
RETURN GET4BYTES(mydris, 329)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSeed1(mydris) && you will want to use these functions if you set the seed values to be random
|
|
RETURN GET4BYTES(mydris, 9)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSeed2(mydris)
|
|
RETURN GET4BYTES(mydris, 13)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisRetCode(mydris)
|
|
RETURN GET4BYTES(mydris, 337)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisExtErr(mydris)
|
|
RETURN GET4BYTES(mydris, 341)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisType(mydris)
|
|
RETURN GET4BYTES(mydris, 345)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisModel(mydris)
|
|
RETURN GET4BYTES(mydris, 349)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSDSN(mydris)
|
|
RETURN GET4BYTES(mydris, 353)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisProdCode(mydris)
|
|
* first find the length of the Product Code
|
|
FOR len = 0 TO 11
|
|
c = SUBSTR(mydris, 357+len, 1)
|
|
IF c = CHR(0)
|
|
EXIT
|
|
ENDIF
|
|
ENDFOR
|
|
RETURN SUBSTR(mydris, 357, len)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisDongleNumber(mydris)
|
|
RETURN GET4BYTES(mydris, 369)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisUpdateNumber(mydris)
|
|
RETURN GET4BYTES(mydris, 373)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisDataAreaSize(mydris)
|
|
RETURN GET4BYTES(mydris, 377)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisMaxAlgNum(mydris)
|
|
RETURN GET4BYTES(mydris, 381)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisExecs(mydris)
|
|
RETURN GET4BYTES(mydris, 385)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisExpDay(mydris)
|
|
RETURN GET4BYTES(mydris, 389)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisExpMonth(mydris)
|
|
RETURN GET4BYTES(mydris, 393)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisExpYear(mydris)
|
|
RETURN GET4BYTES(mydris, 397)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisFeatures(mydris)
|
|
RETURN GET4BYTES(mydris, 401)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisNetUsers(mydris)
|
|
RETURN GET4BYTES(mydris, 405)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisAlgAnswer(mydris)
|
|
RETURN GET4BYTES(mydris, 409)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisFDCapacity(mydris)
|
|
RETURN GET4BYTES(mydris, 413)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisFDDrive(mydris)
|
|
RETURN SUBSTR(mydris, 417, 3)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSWKeyType(mydris)
|
|
RETURN GET4BYTES(mydris, 545)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSWKeyExpDay(mydris)
|
|
RETURN GET4BYTES(mydris, 549)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSWKeyExpMonth(mydris)
|
|
RETURN GET4BYTES(mydris, 553)
|
|
ENDFUNC
|
|
|
|
FUNCTION GetDrisSWKeyExpYear(mydris)
|
|
RETURN GET4BYTES(mydris, 557)
|
|
ENDFUNC
|
|
|
|
|
|
*** displays messages for the most common errors. You will want to change this for your code
|
|
FUNCTION DisplayError(mydris, ret_code)
|
|
DO CASE
|
|
CASE ret_code = 401
|
|
? "Error! No dongles detected!"
|
|
|
|
CASE ret_code = 403
|
|
? "Error! The dongle detected has a different type to the one specified in DinkeyAdd."
|
|
|
|
CASE ret_code = 404
|
|
? "Error! The dongle detected has a different model to those specified in DinkeyAdd."
|
|
|
|
CASE ret_code = 409
|
|
? "Error! The dongle detected has not been programmed by DinkeyAdd."
|
|
|
|
CASE ret_code = 410
|
|
? "Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd."
|
|
|
|
CASE ret_code = 411
|
|
? "Error! The dongle detected does not contain the licence associated with this program."
|
|
|
|
CASE ret_code = 413
|
|
? "Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual."
|
|
|
|
CASE ret_code = 417
|
|
? "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."
|
|
|
|
CASE ret_code = 423
|
|
? "Error! The number of network users has been exceeded."
|
|
|
|
CASE ret_code = 435
|
|
? "Error! DinkeyServer has not been detected on the network."
|
|
|
|
CASE ret_code = 922
|
|
? "Error! The Software Key has expired."
|
|
|
|
OTHERWISE
|
|
? "An error occurred checking the dongle. Error: " + STR(ret_code) + " Extended Error: " + STR(GetDrisExtErr(mydris))
|
|
|
|
ENDCASE
|
|
RETURN
|
|
ENDFUNC
|