Add Original SDK

This commit is contained in:
2026-05-06 07:47:36 +02:00
parent 2915e04380
commit 0ed627517a
674 changed files with 89334 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
Protecting Windev applications with Dinkey Dongle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You should copy all the code in the file "global variables and functions.txt".
These data structures and functions are used by the API sample code. Then copy
the appropriate function(s) from the "protection check functions.txt" file. These
functions implement all the various features of the DInkey Dongle SDK.
Note that 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.
Code marked with !!!! are places where you should customise the sample code so
that it will work properly:
* Change the MY_SDSN value to the value of your SDSN
* Change the MY_PRODCODE value to the value of your Product Code
* Change the MyAlgorithm code (if you call a user algorithm)
* Change the CryptDRIS code (if you encrypt the DRIS)
* Change the CryptApiData (if you encrypt Data you send to our API)
* Change the MyRWAlgorithm code (if encrypt Data you send to our API using the R/W algorithm)
You will also probably want to replace our error messages with your own. However, you should
still display or log any error codes returned by the protection check otherwise you will not
be able to identify the cause of the error. (You can look up error codes in our knowledge
base: microcosm.com/kb).
Note - you should protect dpwin32.dll and not your program. Because your program
is linked to the DLL it is protected. The protected DLL will need to be in the
same folder as your compiled program for it to run correctly.
Note - if you are producing a 64-bit Windows executable you need to protect dpwin64.dll
(instead of dpwin32.dll) and change the "protectdllname" to be "dpwin64.dll"
(this is found in the global variables and functions.txt).
Similarly for Linux you will need to use dplin32.so (32-bit Linux) or dplin64.so (64-bit Linux).
Note - you can also use the Shell Method of protection on WinDev executables.
Note - we have had reports of a bug in early releases of Windev 19 which causes the "Length" ("Taille")
function to return in incorrect value. This bug has been fixed in the February 2014 release of Windev 19.
Tested under Windev Express v12

View File

@@ -0,0 +1,135 @@
//*******************************************************************
// Dinkey Runtime Information structure (DRIS)
GLOBAL
DRIS is composed of
// the first 4 fields are never encrypted
header is a fixed string on 4 // should be set to DRIS
// inputs
size is an int on 4 // size of this structure
seed1 is an int on 4 // seed for data/dris encryption
seed2 is an int on 4 // seed for data/dris encryption
// (maybe encrypted from now on)
dpfunction is an int on 4 // specify only one function
flags is an int on 4 // options for the function selected. To use more than one OR them together: OPTION1 | OPTION2...
execs_decrement is an unsigned int on 4 // amount by which to dec execs if we use flag: DEC_MANY_EXECS
data_crypt_key_num is an int on 4 // number of the key (1-3) that the dongle uses to encrypt or decrypt user data
rw_offset is an unsigned int on 4 // offset in the dongle data area to read or write data
rw_length is an unsigned int on 4 // length of data are to read/write/encrypt/decrypt
rw_data_ptr is a system int // pointer to data to write / be read
alt_licence_name is a fixed string on 256 // protection check for different licence instead of the default one, must be null-terminated
var_a is an int on 4 // variable values for user algorithm
var_b is an int on 4
var_c is an int on 4
var_d is an int on 4
var_e is an int on 4
var_f is an int on 4
var_g is an int on 4
var_h is an int on 4
alg_number is an unsigned int on 4 // the number of the user algorithm that you want to execute
// outputs
ret_code is an int on 4 // return code from the protection check
ext_err is an unsigned int on 4 // extended error
type is an int on 4 // type of dongle detected. 1 = Pro, 2 = FD
model is an int on 4 // model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
sdsn is an int on 4 // Software Developer's Serial Number
prodcode is a fixed string on 12 // Product Code (null-terminated)
dongle_number is an unsigned int on 4
update_number is an unsigned int on 4
data_area_size is an unsigned int on 4 // size of the data area used in the dongle detected
num_algs is an int on 4 // the maximum algorithm number in the dongle detected
execs is an int on 4 // executions left: -1 indicates 'no limit'
exp_day is an int on 4 // expiry day: -1 indicates 'no limit'
exp_month is an int on 4 // expiry month: -1 indicates 'no limit'
exp_year is an int on 4 // expiry year: -1 indicates 'no limit'
features is an unsigned int on 4 // features value
net_users is an int on 4 // maximum number of network users for the dongle detected: -1 indicates 'mo limit'
alg_answer is an int on 4 // answer to the user algorithm executed with the given variable values
fd_capacity is an unsigned int on 4
fd_drive is a fixed string on 128 // drive letter of FD dongle detected e.g. 'f:\'
swkey_type is an int on 4 // 0 = no swkey detected, 1 = temporary software key, 2 = demo software
swkey_exp_day is an int on 4 // software key expiry date (if software key detected)
swkey_exp_month is an int on 4
swkey_exp_year is an int on 4
END
// dpwin32.dll - 32-bit Windows protection module !!!! change this module for 64-bit Windows or Linux or Mac
protectdllname is a string = "dpwin32.dll"
// functions - must specify only one
CONSTANT
PROTECTION_CHECK = 1 // checks for dongle, check program parameters
EXECUTE_ALGORITHM = 2 // protection check + calculate answer for specified algorithm with specified inputs
WRITE_DATA_AREA =3 // protection check + writes dongle data area
READ_DATA_AREA = 4 // protection check + reads dongle data area
ENCRYPT_USER_DATA = 5 // protection check + the dongle will encrypt user data
DECRYPT_USER_DATA = 6 // protection check + the dongle will decrypt user data
FAST_PRESENCE_CHECK = 7 // checks for the presence of the correct dongle only with minimal security, no flags allowed.
STOP_NET_USER = 8 // stops a network user (and doesn't do a protection check)
END
// flags - can specify as many as you like
CONSTANT
DEC_ONE_EXEC = 1 // decrement execs by 1
DEC_MANY_EXECS = 2 // decrement execs by number specified in execs_decrement
START_NET_USER = 4 // starts a network user
USE_FUNCTION_ARGUMENT = 16 // use the extra argument in the function for pointers
CHECK_LOCAL_FIRST = 32 // always look in local ports before looking in network ports
CHECK_NETWORK_FIRST = 64 // always look on the network before looking in local ports
USE_ALT_LICENCE_NAME = 128 // use name specified in alt_licence_name instead of the default one
DONT_SET_MAXDAYS_EXPIRY = 256 // if the max days expiry date has not been calculated then do not do it this time
MATCH_DONGLE_NUMBER = 512 // restrict the search to match the dongle number specified in the DRIS
DONT_RETURN_FD_DRIVE = 1024 // if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
END
// SDSN (software developer's serial number)
CONSTANT
MY_SDSN = 10101 // !!!! change this value to be the value of your SDSN (demo = 10101)
MY_PRODCODE = "DEMO" // !!!! change thus value to be the value of your Product Code
END
// Summary: Sets each element of the DRIS to be a random value. Improves security
// Syntax:
//RandomSet ()
//
PROCEDURE RandomSet()
DRIS_bytes is array of Length(DRIS) 1-byte unsigned int
Transfer(&DRIS_bytes, &DRIS, Length(DRIS)) // copy DRIS to a byte array so we can look at each byte
InitRandom()
FOR i = 1 _TO_ Length(DRIS)
DRIS_bytes[i] = Random(0,255) // set each element to a random number
END
Transfer(&DRIS, &DRIS_bytes, Length(DRIS)) // copy back to DRIS
// Summary: Displays the error code with a helpful error message. You may want to change the messages.
// Syntax:
//DisplayError (<ret_code> is int, <ext_err> is 4-byte unsigned int)
//
// Parameters:
// ret_code (int): <specify the role of ret_code>
// ext_err (4-byte unsigned int): <specify the role of ext_err>
// Return Value:
// None
//
//
PROCEDURE DisplayError(ret_code is int, ext_err is unsigned int)
SWITCH ret_code
CASE 401: Info("Error! No dongles detected!")
CASE 403: Info("Error! The dongle detected has a different type to the one specified in DinkeyAdd.")
CASE 404: Info("Error! The dongle detected has a different model to those specified in DinkeyAdd.")
CASE 409: Info("Error! The dongle detected has not been programmed by DinkeyAdd.")
CASE 410: Info("Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd.")
CASE 411: Info("Error! The dongle detected does not contain the licence associated with this program.")
CASE 413: Info("Error! This program has not been protected by DinkeyAdd.","For guidance please read the DinkeyAdd chapter of the Dinkey manual.")
CASE 417: Info("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 423: Info("Error! The number of network users has been exceeded.")
CASE 435: Info("Error! DinkeyServer has not been detected on the network.")
CASE 922: Info("Error! The Software Key has expired.")
OTHER CASE: Info("An error occurred checking the dongle.","Error: " + ret_code, "Extended Error: " + ext_err)
END

View File

@@ -0,0 +1,784 @@
// This code contains the following functions. Please choose the one that matches your needs:
// ProtCheck
// ProtCheckWithAlg (the function also depends on the function MyAlgorithm)
// WriteString
// ReadString
// EncryptUserData
// or the same functions but using DRIS and API data encryption
// (these functions also require the functions CryptDRIS and possibly CryptApiData and MyRWAlgorithm)
// ProtCheckEnc
// ProtCheckWithAlgEnc
// WriteStringEnc
// ReadStringEnc
// EncryptUserDataEnc
// Summary: does a standard protection check
// Syntax:
//[ <Result> = ] ProtCheck ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheck()
hLib, ret_code are system int
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = 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...
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
Info("It worked!")
// Summary: does a standard protection check and executes an algorithm
// 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
// Syntax:
//[ <Result> = ] ProtCheckWithAlg ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckWithAlg()
hLib, ret_code are system int
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = EXECUTE_ALGORITHM // protection check and execute specified 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
// !!!! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
DRIS.var_a = 1 // sample values
DRIS.var_b = 2
DRIS.var_c = 3
DRIS.var_d = 4
DRIS.var_e = 5
DRIS.var_f = 6
DRIS.var_g = 7
DRIS.var_h = 8
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
DelayBeforeClosing(1000)
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
// 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) THEN
Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
RESULT -1
END
Info("It worked!")
// Summary:
// !!!! 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 can modify the C code to make it compatiable with Windev.
// Syntax:
//[ <Result> = ] MyAlgorithm (<var_a> is int, <var_b> is int, <var_c> is int, <var_d> is int, <var_e> is int, <var_f> is int, <var_g> is int, <var_h> is int)
//
PROCEDURE MyAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, var_g is int, var_h is int)
RESULT var_a + var_b + var_c + var_d + var_e + var_f + var_g + var_h
// Summary: This function does a protection check and writes the string "Hello, World!" to the 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.
// NB you can easily modify the code to write a byte array instead of a string
// Syntax:
//[ <Result> = ] WriteString ()
// return value is 0 (success) or an error code
//
PROCEDURE WriteString()
hLib, ret_code are system int
OurString is fixed string on 1024 = "Hello, World!" // NB max. data write is 1K
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = WRITE_DATA_AREA // protection check and write specified 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 = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
Info("It worked!")
// Summary: This function does a protection check and reads 13 bytes of data from the 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.
// NB you can amend this code to read a byte array instead of a string if you prefer.
// Syntax:
//[ <Result> = ] ReadString ()
// return value is 0 (success) or an error code
//
PROCEDURE ReadString()
hLib, ret_code are system int
OurString is fixed string on 1024 // NB max. data read is 1K
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = READ_DATA_AREA // 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 = 13
DRIS.rw_data_ptr = &OurString
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
// Summary: 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. NB you can modify the code to encrypt byte arrays instead of strings
// NB you can amend this code to read a byte array instead of a string if you prefer.
// Syntax:
//[ <Result> = ] EncryptUserData ()
// return value is 0 (success) or an error code
//
PROCEDURE EncryptUserData()
hLib, ret_code are system int
OurString is fixed string on 1024 = "Hello, World!" // NB max. data we can encrypt is 1K
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = ENCRYPT_USER_DATA // protection check and encrypt specified 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 = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
FreeDLL(hLib)
RESULT ret_code
END
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
// Now decrypt the same data to get the original values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = DECRYPT_USER_DATA // protection check and decrypt specified 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 = 13 // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString // NB the data is encrypted at this point
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
// !!!!!!!!!!! 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 (you will have to adapt the C code generated by DinkeyAdd)
PROCEDURE MyRWAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, nVar_g is int, nVar_h is int)
RESULT BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(var_a, var_b), var_c), var_d), var_e), var_f)
// !!!! please overwrite this function with the one generated by DinkeyAdd
// (just modify the parameters specified in DinkeyAdd in the positiions indicated below):
// Note arrays in Windev are 1-base which makes it a real pain
PROCEDURE CryptDRIS()
i, j, k are int
bigseed, S are array of 256 1-byte unsigned int
DRIS_bytes is an array of Length(DRIS) 1-byte unsigned int
temp, t are 1-byte unsigned int
FOR i = 1 _TO_ 256 STEP 8
Transfer(&bigseed[i], &DRIS.seed1, 4)
Transfer(&bigseed[i+4], &DRIS.seed2, 4)
END
FOR i = 0 _TO_ 255
S[i+1] = i
END
j = 0
FOR i = 0 _TO_ 255
j = (j + S[i+1] + bigseed[i+1] + 123) modulo 256 // parameter 1, modify 123
temp = S[i+1]
S[i+1] = S[j+1]
S[j+1] = temp
END
Transfer(&DRIS_bytes, &DRIS, Length(DRIS)) // convert DRIS to bytes
i = 0
j = 0
FOR k = 17 _TO_ Length(DRIS)
i = (i + 1) modulo 256
j = (j + S[i+1] + 212) modulo 256 // parameter 2, modify 212
temp = S[i+1]
S[i+1] = S[j+1]
S[j+1] = temp
t = (S[i+1] + S[j+1] + 97) modulo 256 // parameter 3, modify 97
DRIS_bytes[k] = BinaryXOR(DRIS_bytes[k], S[t+1])
END
Transfer(&DRIS, &DRIS_bytes, Length(DRIS)) // convert back again
// Note arrays in Windev are 1-base which makes it a real pain
// Summary: <specify the procedure action>
// Syntax:
//CryptApiData (<data>, <enc_length> is 4-byte unsigned int, <alg_ans> is int)
PROCEDURE CryptApiData(data, enc_length is unsigned int, alg_ans is int)
i, j, k are int
bigseed, S are array of 256 1-byte unsigned int
temp, t are 1-byte unsigned int
FOR i = 1 _TO_ 256 STEP 8
Transfer(&bigseed[i], &DRIS.seed1, 4)
Transfer(&bigseed[i+4], &DRIS.seed2, 4)
END
FOR i = 0 _TO_ 255
S[i+1] = i
END
j = 0
FOR i = 0 _TO_ 255
j = (j + S[i+1] + bigseed[i+1] + BinaryAND(alg_ans, 0xff)) modulo 256
temp = S[i+1]
S[i+1] = S[j+1]
S[j+1] = temp
END
i = 0
j = 0
FOR k = 1 _TO_ enc_length
i = (i + 1) modulo 256
j = (j + S[i+1] + (BinaryAND(alg_ans, 0xff00))/256) modulo 256
temp = S[i+1]
S[i+1] = S[j+1]
S[j+1] = temp
t = (S[i+1] + S[j+1] + (BinaryAND(alg_ans, 0xff0000))/65536) modulo 256
data[k] = BinaryXOR(data[k], S[t+1])
END
// Summary: does a standard protection check and encrypt the DRIS we pass and from the API.
// We encrypt the DRIS passed to the API. !!!! Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] ProtCheckEnc ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckEnc()
hLib, ret_code are system int
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = 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...
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
Info("It worked!")
// Summary: does a standard protection check and executes an algorithm and encrypts the DRIS
// NB for this to work you must program at least one "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.
// Syntax:
//[ <Result> = ] ProtCheckWithAlgEnc ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckWithAlgEnc()
hLib, ret_code are system int
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = EXECUTE_ALGORITHM // protection check and execute specified 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
// !!!! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
DRIS.var_a = 1 // sample values
DRIS.var_b = 2
DRIS.var_c = 3
DRIS.var_d = 4
DRIS.var_e = 5
DRIS.var_f = 6
DRIS.var_g = 7
DRIS.var_h = 8
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
DelayBeforeClosing(1000)
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
// 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) THEN
Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
RESULT -1
END
Info("It worked!")
// Summary: This function does a protection check and writes the string "Hello, World!" to the 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.
// NB you can easily modify the code to write a byte array instead of a string
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] WriteStringEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE WriteStringEnc()
hLib, ret_code are system int
alg_ans are int
OurString is fixed string on 1024 = "Hello, World!" // NB max. data write is 1K
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = WRITE_DATA_AREA // protection check and write specified 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 = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes // we convert the string to write to a byte array (so we can encrypt it) and then we pass that value to our API
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
alg_ans = 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 (we must first convert it to a byte array so we can encrypt)
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
Info("It worked!")
// Summary: This function does a protection check and reads 13 bytes of data from the 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.
// NB you can amend this code to read a byte array instead of a string if you prefer.
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] ReadStringEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE ReadStringEnc()
hLib, ret_code are system int
alg_ans are int
OurString is fixed string on 1024 // NB max. data read is 1K
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = READ_DATA_AREA // 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 = 13
DRIS.rw_data_ptr = &OurString_bytes // read it to our byte array first and then convert to a string
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
alg_ans = 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() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
RESULT -1
END
IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
RESULT -1
END
// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
Info("Dinkey Dongle protection error")
RESULT -1
END
// decrypt data we have just read (then convert to string)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)
// Summary: 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. NB you can modify the code to encrypt byte arrays instead of strings
// NB you can amend this code to read a byte array instead of a string if you prefer.
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] EncryptUserDataEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE EncryptUserDataEnc()
hLib, ret_code are system int
alg_ans is int
OurString is fixed string on 1024 = "Hello, World!" // NB max. data we can encrypt is 1K
OurString_bytes is array of 1024 1-byte unsigned int // byte-array of the encrypted string
// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = ENCRYPT_USER_DATA // protection check and encrypt specified 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 = Length(Left(OurString)) // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes // we convert the string to encrypt to a byte array (so we can encrypt it) and then we pass that to the API
// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
RESULT -1
END
// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
alg_ans = 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 (we must first convert it to a byte array so we can encrypt)
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
CryptDRIS() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
FreeDLL(hLib)
RESULT ret_code
END
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
// Now decrypt the same data to get the original values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = DECRYPT_USER_DATA // protection check and decrypt specified 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 = 13 // the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes // NB this wil still be the encrypted data at this point
alg_ans = 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() // encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)
CryptDRIS() // decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
IF ret_code <> 0 THEN // an error occured so display an appropriate error message
DisplayError(ret_code, DRIS.ext_err)
RESULT ret_code
END
// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)
// decrypt the returned value and convert to a string
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)