Files
PS_Dinkey/Dinkey Pro 7.6.1/Samples/FoxPro/runtime.prg
2026-05-06 07:47:36 +02:00

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