Add Original SDK
This commit is contained in:
69
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/DllTest.lfproj
Normal file
69
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/DllTest.lfproj
Normal file
@@ -0,0 +1,69 @@
|
||||
<Project Version="8.00" DefaultTargets="Link" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<UsingTask TaskName="LF_Tasks.LFC" AssemblyFile="$(PackageRoot)\FortranTasks.dll" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{76ddb05e-4dea-4d83-98ce-e740d0bc7426}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>DllTest</AssemblyName>
|
||||
<PackageRoot>C:\Program Files (x86)\Lahey-Fujitsu Fortran\v7.2\Visual Studio 2008\Packages</PackageRoot>
|
||||
<OutputName>DllTest.exe</OutputName>
|
||||
<DLL>False</DLL>
|
||||
<Name>DllTest</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<OptLevel>O0</OptLevel>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DeallocateLocals>False</DeallocateLocals>
|
||||
<Pause>True</Pause>
|
||||
<TraceBack>True</TraceBack>
|
||||
<StackChk>True</StackChk>
|
||||
<MixLang>MSVC</MixLang>
|
||||
<OptLevel>O0</OptLevel>
|
||||
<CodeGenerationTarget>default</CodeGenerationTarget>
|
||||
<LibPath>..\..\C\import_libs</LibPath>
|
||||
<AdditionalLnkOpts>dpwin32.lib</AdditionalLnkOpts>
|
||||
<LinkOptions>-g|-ndal|-ml MSVC|-o0|-pause|-stchk|-trace|-libpath "..\..\C\import_libs"|"dpwin32.lib"</LinkOptions>
|
||||
<Blas>False</Blas>
|
||||
<Comment>
|
||||
</Comment>
|
||||
<Lapack>False</Lapack>
|
||||
<NoLogo>False</NoLogo>
|
||||
<SSL2>False</SSL2>
|
||||
<Stack>
|
||||
</Stack>
|
||||
<StaticLib>True</StaticLib>
|
||||
<OutputName>DllTest.exe</OutputName>
|
||||
<MixLangDef>LF95</MixLangDef>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DeallocateLocals>False</DeallocateLocals>
|
||||
<Pause>True</Pause>
|
||||
<DisplayWarnings>False</DisplayWarnings>
|
||||
<MixLang>MSVC</MixLang>
|
||||
<CodeGenerationTarget>default</CodeGenerationTarget>
|
||||
<LibPath>..\..\C\import_libs</LibPath>
|
||||
<AdditionalLnkOpts>dpwin32.lib</AdditionalLnkOpts>
|
||||
<LinkOptions>-ndal|-ml MSVC|-nw|-pause|-libpath "..\..\C\import_libs"|dpwin32.lib</LinkOptions>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="dlltest.f90">
|
||||
<SubType>Code</SubType>
|
||||
<FileExt>.obj</FileExt>
|
||||
<FortranOptions>-g|-ndal|-ml MSVC|-o0|-pause|-stchk|-trace</FortranOptions>
|
||||
<CompileOrder>1</CompileOrder>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Target Name="Link" DependsOnTargets="Build" Inputs="@(Compile -> '%(Filename)%(FileExt)')" Outputs="$(OutputPath)$(OutputName)">
|
||||
<LFC Source="@(Compile -> '%(Filename)%(FileExt)')" OutputName="$(OutputPath)$(OutputName)" Options="$(LinkOptions)" />
|
||||
</Target>
|
||||
<Target Name="Build" Inputs="@(Compile)" Outputs="@(Compile -> '%(Filename)%(FileExt)')">
|
||||
<LFC Source="%(Compile.FullPath)" CompileOnly="-c" Options="%(Compile.FortranOptions)|$(ProjectOptions)" />
|
||||
</Target>
|
||||
<Target Name="Clean">
|
||||
<LFC Clean="True" Source="%(Compile.FullPath)" OutputName="$(OutputPath)$(OutputName)" />
|
||||
</Target>
|
||||
<Target Name="Rebuild" DependsOnTargets="Clean; Link" />
|
||||
</Project>
|
||||
19
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/DllTest.sln
Normal file
19
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/DllTest.sln
Normal file
@@ -0,0 +1,19 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{B7CA1DD7-A797-4295-BB4F-1411A8008584}") = "DllTest", "DllTest.lfproj", "{76DDB05E-4DEA-4D83-98CE-E740D0BC7426}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{76DDB05E-4DEA-4D83-98CE-E740D0BC7426}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{76DDB05E-4DEA-4D83-98CE-E740D0BC7426}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{76DDB05E-4DEA-4D83-98CE-E740D0BC7426}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{76DDB05E-4DEA-4D83-98CE-E740D0BC7426}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
76
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/README.txt
Normal file
76
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/README.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
Fortran Sample Code notes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We supply separate sample code for different compilers as they all seem to compile Fortran
|
||||
slightly differently! In general the code is the same. The differences are in defining the
|
||||
DDProtCheck function in our runtime dll and in using random_set and CryptDris functions.
|
||||
The Intel compiler is much stricter and so the code is more complicated in this case
|
||||
(we must use "equivalence" so we can treat the DRIS type as a byte array in some cases).
|
||||
|
||||
Lahey Fortran Sample Code tested using 32-bit Lahey Fortran 7.2 and Visual Studio 2008
|
||||
Intel Fortran Sample Code tested using 32-bit and 64-bit Intel Fortran XE 2011 compiler & VS 2008
|
||||
(also tested with Intel Fortran 10.1 compiler but see note at the bottom of this file).
|
||||
|
||||
g95 has some unusual restrictions such as 132 characters for a line length. Only tested
|
||||
with 32-bit code.
|
||||
|
||||
We have not tested with GFortran but the code should be similar to g95.
|
||||
|
||||
Description of files:
|
||||
|
||||
dlltest.f90 Fortran sample code for Lahey Fortran
|
||||
DllTest.lfproj Visual Studio 2008 Project using Lahey Fortran
|
||||
Dlltest.sln Visual Studio 2008 Solution for Lahey Fortran
|
||||
|
||||
idlltest.f90 Fortran sample code for Intel Fortran
|
||||
iDllTest.vfproj Visual Studio 2008 Project using Intel Fortran
|
||||
iDlltest.sln Visual Studio 2008 Solution for Intel Fortran
|
||||
|
||||
gdlltest.f90 Fortan code using by g95 compiler.
|
||||
|
||||
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.
|
||||
|
||||
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 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.
|
||||
|
||||
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 - once dpwin32.dll is protected you will not be able to debug your program -
|
||||
after our API has been called. Our strong anti-debug code will cause the debugger
|
||||
to throw an exception. If you do want to debug your code then you can use our debug
|
||||
module: dpwin32debug.dll, but this should not be used for release. See readme.txt
|
||||
in samples\c for restrictions concerning the debug module.
|
||||
|
||||
Note - if you do not use Lahey/Intel Fortran or you use an earlier version of Visual Studio then
|
||||
you will have to create the solution & project yourself. (Newer versions of Visual Studio will
|
||||
update the project for you). It is not difficult. You have to link with the import library
|
||||
(which is in Microsoft format) dpwin32.lib (so your program knows how our API functions are
|
||||
formatted and the DLL name). For 64-bit compilations you link with dpwin64.lib. Both of these
|
||||
files are in the Modules\import_libs folder (also in Samples\C\import_libs). You should list
|
||||
this files in Project Settings | Linker | Input | Addition Dependencies.
|
||||
|
||||
Note - the Lahey sample only works with 32-bit Fortran (because that is all Lahey supports currently).
|
||||
The code should work with 64-bit Fortran also. However, you will have to change the "unused" element
|
||||
in the DRIS to be integer(8). i.e. 8 bytes and change DRIS_SIZE to 548.
|
||||
|
||||
Note - there appears to be a small bug in the 64-bit Intel 10.1 Fortran compiler. If you use this
|
||||
then you need to remove the word DECORATE in the DDProtCheck function declaration. This keyword is
|
||||
needed for the 32-bit compiler.
|
||||
|
||||
Note - For g95 you should compile like this (for example):
|
||||
g95 -Wno=101 gdlltest.f90 -B c:\c95\lib dpwin32.dll -o gDllTest.exe
|
||||
(the -Wno=101 removes warnings about the EQUIVALENCE statement we have to use in the sample)
|
||||
797
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/dlltest.f90
Normal file
797
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/dlltest.f90
Normal file
@@ -0,0 +1,797 @@
|
||||
! dlltest - sample program to call DinkeyPro/FD runtime module (dpwin32.dll)
|
||||
!
|
||||
! this sample code has been compiled and tested using Lahey Fortran v7.2
|
||||
|
||||
! The sample code contains 10 functions. You will not need to use all these
|
||||
! functions in your code. Just use which ever functions are most appropriate
|
||||
! and customise in your own way. The sample code is just a guide. You should
|
||||
! implement the protection in a stronger way using the techniques described in
|
||||
! the "Increasing your Protection" chapter of the manual.
|
||||
|
||||
!If you are using Dinkey Lite then you can only use 4 functions:
|
||||
!ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
||||
|
||||
! this file contains 10 protection-check functions.
|
||||
! ProtCheck a standard protection check
|
||||
! ProtCheckWithAlg a protection check & executing an algorithm
|
||||
! WriteBytes a protection check & write data to the dongle
|
||||
! ReadBytes a protection check & read data from the dongle
|
||||
! EncryptUserData a protection check & encrypting data and then decrypting the data
|
||||
! these functions are the same as the functions listed above but encrypting all parameters passed to our API
|
||||
! ProtCheckEnc a standard protection check
|
||||
! ProtCheckWithAlgEnc a protection check & executing an Algorithm
|
||||
! WriteBytesEnc a protection check & write data to the dongle
|
||||
! ReadBytesEnc a protection check & read data from the dongle
|
||||
! EncryptUserDataEnc a protection check & encrypting data and then decrypting the data
|
||||
|
||||
PROGRAM main
|
||||
! call the function(s) of your choice here
|
||||
! by default I have chosen a standard protection check
|
||||
if (ProtCheck() == 0) then
|
||||
print *,"It worked!"
|
||||
end if
|
||||
END PROGRAM main
|
||||
|
||||
! this module contains the DRIS structure declaration and also declares important constants
|
||||
MODULE DinkeyPro
|
||||
|
||||
integer,parameter :: MY_SDSN = 10101 !!!! change this value to be the value of your SDSN (demo = 10101)
|
||||
|
||||
! declare dris data type
|
||||
TYPE DRIS
|
||||
sequence
|
||||
! the first 4 fields are never encrypted
|
||||
character(len=4) :: header ! should be set to 'DRIS'
|
||||
! inputs
|
||||
integer(4) :: size ! size of this structure
|
||||
integer(4) :: seed1 ! seed for data/dris encryption
|
||||
integer(4) :: seed2 ! as above
|
||||
! (maybe encrypted from now on)
|
||||
integer(4) :: function ! specify only one function
|
||||
integer(4) :: flags ! options for the function selected. To use more than one OR them together e.g. OR(OPTION1, OPTION2)
|
||||
integer(4) :: execs_decrement ! amount by which to dec execs if we use flag: DEC_MANY_EXECS
|
||||
integer(4) :: data_crypt_key_num ! number of the key (1-3) that the dongle uses to encrypt or decrypt user data
|
||||
integer(4) :: rw_offset ! offset in the dongle data area to read or write data
|
||||
integer(4) :: rw_length ! length of data are to read/write/encrypt/decrypt
|
||||
integer(4) :: unused ! pass data by function parameter instead. This field should be 8 bytes long for 64-bit Fortran code
|
||||
character(len=256) :: alt_licence_name ! protection check for different licence instead of the default one, must be null-terminated
|
||||
integer(4) :: var_a ! variable values for user algorithm
|
||||
integer(4) :: var_b
|
||||
integer(4) :: var_c
|
||||
integer(4) :: var_d
|
||||
integer(4) :: var_e
|
||||
integer(4) :: var_f
|
||||
integer(4) :: var_g
|
||||
integer(4) :: var_h
|
||||
integer(4) :: alg_number ! the number of the user algorithm that you want to execute
|
||||
|
||||
! outputs
|
||||
integer(4) :: ret_code ! return code from the protection check
|
||||
integer(4) :: ext_err ! extended error
|
||||
integer(4) :: type ! type of dongle detected. 1 = Pro, 2 = FD
|
||||
integer(4) :: model ! model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
|
||||
integer(4) :: sdsn ! Software Developer's Serial Number
|
||||
character(len=12) :: prodcode ! Product Code (null-terminated)
|
||||
integer(4) :: dongle_number ! NB this should be an unsigned value really
|
||||
integer(4) :: update_number
|
||||
integer(4) :: data_area_size ! size of the data area used in the dongle detected
|
||||
integer(4) :: max_alg_num ! the maximum algorithm number in the dongle detected
|
||||
integer(4) :: execs ! executions left: -1 indicates 'no limit'
|
||||
integer(4) :: exp_day ! expiry day: -1 indicates 'no limit'
|
||||
integer(4) :: exp_month ! expiry month: -1 indicates 'no limit'
|
||||
integer(4) :: exp_year ! expiry year: -1 indicates 'no limit'
|
||||
integer(4) :: features ! features value
|
||||
integer(4) :: net_users ! maximum number of network users for the dongle detected: -1 indicates 'no limit'
|
||||
integer(4) :: alg_answer ! answer to the user algorithm executed with the given variable values
|
||||
integer(4) :: fd_capacity ! capacity of the data area in FD dongle.
|
||||
character(len=128) :: fd_drive ! drive letter of FD dongle detected e.g. 'f:\' (or mount name under Linux)
|
||||
integer(4) :: swkey_type ! 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
|
||||
integer(4) :: swkey_exp_day ! software key expiry date (if software key detected)
|
||||
integer(4) :: swkey_exp_month
|
||||
integer(4) :: swkey_exp_year
|
||||
END TYPE DRIS
|
||||
|
||||
integer,parameter :: DRIS_SIZE = 560 ! I am sure there should be a way to get this programatically!
|
||||
|
||||
! functions - must specify only one
|
||||
integer,parameter :: PROTECTION_CHECK = 1 ! checks for dongle, check program params...
|
||||
integer,parameter :: EXECUTE_ALGORITHM = 2 ! protection check + calculate answer for specified algorithm with specified inputs
|
||||
integer,parameter :: WRITE_DATA_AREA = 3 ! protection check + writes dongle data area
|
||||
integer,parameter :: READ_DATA_AREA = 4 ! protection check + reads dongle data area
|
||||
integer,parameter :: ENCRYPT_USER_DATA = 5 ! protection check + the dongle will encrypt user data
|
||||
integer,parameter :: DECRYPT_USER_DATA = 6 ! protection check + the dongle will decrypt user data
|
||||
integer,parameter :: FAST_PRESENCE_CHECK = 7 ! checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
||||
integer,parameter :: STOP_NET_USER = 8 ! stops a network user (a protection check is NOT performed)
|
||||
|
||||
! flags - can specify as many as you like
|
||||
integer,parameter :: DEC_ONE_EXEC = 1 ! decrement execs by 1
|
||||
integer,parameter :: DEC_MANY_EXECS = 2 ! decrement execs by number specified in execs_decrement
|
||||
integer,parameter :: START_NET_USER = 4 ! starts a network user
|
||||
integer,parameter :: STOP_NET_USER = 8 ! stops a network user (a protection check is NOT performed)
|
||||
integer,parameter :: USE_FUNCTION_ARGUMENT = 16 ! use the extra argument in the function for pointers
|
||||
integer,parameter :: CHECK_LOCAL_FIRST = 32 ! always look in local ports before looking in network ports
|
||||
integer,parameter :: CHECK_NETWORK_FIRST = 64 ! always look on the network before looking in local ports
|
||||
integer,parameter :: USE_ALT_LICENCE_NAME = 128 ! use name specified in alt_licence_name instead of this program name
|
||||
integer,parameter :: DONT_SET_MAXDAYS_EXPIRY = 256 ! if the max days expiry date has not been calculated then do not do it this time
|
||||
integer,parameter :: MATCH_DONGLE_NUMBER = 512 ! restrict the search to match the dongle number specified in the DRIS
|
||||
integer,parameter :: DONT_RETURN_FD_DRIVE = 1024 ! if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
||||
|
||||
! declare the protection check function in the Dinkey Pro/FD runtime module
|
||||
DLL_IMPORT DDProtCheck
|
||||
type (DRIS) mydris
|
||||
integer DDProtCheck
|
||||
|
||||
END MODULE DinkeyPro
|
||||
|
||||
! ************************* our 10 functions **********************************
|
||||
|
||||
! ************************** ProtCheck ***************************************
|
||||
FUNCTION ProtCheck()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheck = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! sample to show how to display dongle number (this is the only value in the dris that should be an unsigned integer)
|
||||
integer(8) :: display_dongle_number
|
||||
display_dongle_number = mydris%dongle_number
|
||||
call ConvertDongleNumber(display_dongle_number)
|
||||
print *,"Dongle Check successful. Dongle Number is: ",display_dongle_number
|
||||
END FUNCTION ProtCheck
|
||||
|
||||
! ************************** 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.
|
||||
FUNCTION MyAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyAlgorithm
|
||||
MyAlgorithm = a + b + c + d + e + f + g + h
|
||||
return
|
||||
END FUNCTION MyAlgorithm
|
||||
|
||||
! 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckWithAlg = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h) <> mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlg
|
||||
|
||||
! ************************** WriteBytes ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=*),parameter :: WriteData = "Hello, World!"
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytes = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytes
|
||||
|
||||
! ************************** ReadBytes ***************************************
|
||||
! This reads 14 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=14) :: ReadData
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytes = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytes
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=13) :: Data = "Hello, World!"
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(Data)
|
||||
|
||||
ret_code = DDProtCheck(mydris, Data)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",Data
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(Data)
|
||||
|
||||
ret_code = DDProtCheck(mydris, Data)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Decrypted data is: ",Data
|
||||
END FUNCTION EncryptUserData
|
||||
|
||||
! !!!!!!!!!!! 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
|
||||
FUNCTION MyRWAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyAlgorithm
|
||||
MyRWAlgorithm = IEOR(IEOR(IEOR(IEOR(IEOR(a,b),c),d),e),f)
|
||||
return
|
||||
END FUNCTION MyRWAlgorithm
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
SUBROUTINE CryptDRIS(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer :: i,j,k,temp,t
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + 123, 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=17,DRIS_SIZE
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + 212, 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + 97,255) ! third parameter patched here
|
||||
dris_byte_array(k) = IEOR(dris_byte_array(k),S(t+1))
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptDRIS
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
! if you are using the r/w algorithm then there is no need to change this function
|
||||
! NB we pass the whole of the DRIS but we only need it for seed1 and seed2 values
|
||||
SUBROUTINE CryptApiData(data, length, dris_byte_array, alg_answer)
|
||||
use DinkeyPro
|
||||
integer :: length, alg_answer, seed1, seed2
|
||||
integer(1), dimension(length) :: data
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer :: i,j,k,temp,t
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + IAND(alg_answer, 255), 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=1,length
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + IAND(ISHFT(alg_answer, -8),255), 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + IAND(ISHFT(alg_answer, -16),255),255) ! third parameter patched here
|
||||
data(k) = IEOR(data(k),S(t+1))
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptApiData
|
||||
|
||||
! ************************** ProtCheckEnc ***************************************
|
||||
! We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ProtCheckEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckEnc
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckWithAlgEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h) <> mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlgEnc
|
||||
|
||||
! ************************** WriteBytesEnc ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=*),parameter :: WriteData = "Hello, World!"
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
! encrypt data we want to write.
|
||||
call CryptApiData(WriteData, len(WriteData), mydris, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytesEnc
|
||||
|
||||
! ************************** ReadBytesEnc ***************************************
|
||||
! This reads 14 bytes of data from offset 7 in the dongle data area
|
||||
! In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
||||
! In order for the data to be displayed properly by this routine it will need to be text data
|
||||
! We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ReadBytesEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: ReadData
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! decrypt data we have just read.
|
||||
call CryptApiData(ReadData, len(ReadData), mydris, alg_ans);
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytesEnc
|
||||
|
||||
! ************************** EncryptUserDataEnc ***************************************
|
||||
! This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
||||
! It will then do another protection check & decrypt the data
|
||||
! We encrypt the DRIS and Data passed to/from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION EncryptUserDataEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=13) :: Data = "Hello, World!"
|
||||
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(Data)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
! encrypt data we want to pass.
|
||||
call CryptApiData(Data, len(Data), mydris, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, Data)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",Data
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(Data)
|
||||
|
||||
call CryptDRIS(mydris) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, Data)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code <> 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn <> MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code <> 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
! decrypt data that was passed to us by the API.
|
||||
call CryptApiData(Data, len(Data), mydris, alg_ans);
|
||||
print *,"Decrypted data is: ",Data
|
||||
END FUNCTION EncryptUserDataEnc
|
||||
|
||||
|
||||
! ************************** useful subroutines *******************************
|
||||
! subroutine to randomise each element of the DRIS
|
||||
SUBROUTINE set_random(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
real,dimension(DRIS_SIZE) :: temp
|
||||
|
||||
call random_seed()
|
||||
call random_number(temp)
|
||||
do i=1,DRIS_SIZE
|
||||
dris_byte_array(i) = temp(i)*256
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE set_random
|
||||
|
||||
! subroutine to convert an unsigned integer (stored as a signed integer) to the correct unsigned value (for display purposes)
|
||||
! e.g. the dongle_number value in the dris - should be an unsigned integer but Fortran 90 does not support them
|
||||
SUBROUTINE ConvertDongleNumber(value)
|
||||
integer(8) :: value
|
||||
|
||||
if (value < 0) then
|
||||
value = value + 4294967296 ! make the -ve value a +ve value
|
||||
end if
|
||||
return
|
||||
END SUBROUTINE ConvertDongleNumber
|
||||
|
||||
! displays messages for the most common errors. You will want to change this for your code
|
||||
SUBROUTINE DisplayError(ret_code, extended_error)
|
||||
integer :: ret_code, extended_error
|
||||
|
||||
select case (ret_code)
|
||||
case (401)
|
||||
print *,"Error! No dongles detected!"
|
||||
case (403)
|
||||
print *,"Error! The dongle detected has a different type to the one specified in DinkeyAdd."
|
||||
case (404)
|
||||
print *,"Error! The dongle detected has a different model to those specified in DinkeyAdd."
|
||||
case (409)
|
||||
print *,"Error! The dongle detected has not been programmed by DinkeyAdd."
|
||||
case (410)
|
||||
print *,"Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd."
|
||||
case (411)
|
||||
print *,"Error! The dongle detected does not contain the licence associated with this program."
|
||||
case (413)
|
||||
print *,"Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual."
|
||||
case (417)
|
||||
print *,"Error! One or more of the parameters set in the DRIS is incorrect. This could be caused if you are encrypting the DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa."
|
||||
case (423)
|
||||
print *,"Error! The number of network users has been exceeded."
|
||||
case (435)
|
||||
print *,"Error! DinkeyServer has not been detected on the network."
|
||||
case (922)
|
||||
print *,"Error! The Software Key has expired."
|
||||
case default
|
||||
print *,"An error occurred checking the dongle. Error: ", ret_code, " Extended Error: ", extended_error
|
||||
end select
|
||||
return
|
||||
END SUBROUTINE DisplayError
|
||||
862
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/gdlltest.f90
Normal file
862
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/gdlltest.f90
Normal file
@@ -0,0 +1,862 @@
|
||||
! dlltest - sample program to call DinkeyPro/FD runtime module (dpwin32.dll)
|
||||
!
|
||||
! this sample code has been compiled and tested using g95. It should also work for GFortran
|
||||
! but this has not been tested
|
||||
|
||||
! The sample code contains 10 functions. You will not need to use all these
|
||||
! functions in your code. Just use which ever functions are most appropriate
|
||||
! and customise in your own way. The sample code is just a guide. You should
|
||||
! implement the protection in a stronger way using the techniques described in
|
||||
! the "Increasing your Protection" chapter of the manual.
|
||||
|
||||
!If you are using Dinkey Lite then you can only use 4 functions:
|
||||
!ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
||||
|
||||
! this file contains 10 protection-check functions.
|
||||
! ProtCheck a standard protection check
|
||||
! ProtCheckWithAlg a protection check & executing an algorithm
|
||||
! WriteBytes a protection check & write data to the dongle
|
||||
! ReadBytes a protection check & read data from the dongle
|
||||
! EncryptUserData a protection check & encrypting data and then decrypting the data
|
||||
! these functions are the same as the functions listed above but encrypting all parameters passed to our API
|
||||
! ProtCheckEnc a standard protection check
|
||||
! ProtCheckWithAlgEnc a protection check & executing an Algorithm
|
||||
! WriteBytesEnc a protection check & write data to the dongle
|
||||
! ReadBytesEnc a protection check & read data from the dongle
|
||||
! EncryptUserDataEnc a protection check & encrypting data and then decrypting the data
|
||||
|
||||
PROGRAM main
|
||||
! call the function(s) of your choice here
|
||||
! by default I have chosen a standard protection check
|
||||
if (ProtCheck() == 0) then
|
||||
print *,"It worked!"
|
||||
end if
|
||||
END PROGRAM main
|
||||
|
||||
! this module contains the DRIS structure declaration and also declares important constants
|
||||
MODULE DinkeyPro
|
||||
|
||||
integer,parameter :: MY_SDSN = 10101 !!!! change this value to be the value of your SDSN (demo = 10101)
|
||||
|
||||
! declare dris data type
|
||||
! It would be nice if there were a compiler directive ensuring byte alignment for this type. I can't find one but it seems to be byte aligned anyway ;)
|
||||
TYPE DRIS
|
||||
sequence
|
||||
! the first 4 fields are never encrypted
|
||||
character(len=4) :: header ! should be set to 'DRIS'
|
||||
! inputs
|
||||
integer(4) :: size ! size of this structure
|
||||
integer(4) :: seed1 ! seed for data/dris encryption
|
||||
integer(4) :: seed2 ! as above
|
||||
! (maybe encrypted from now on)
|
||||
integer(4) :: function ! specify only one function
|
||||
integer(4) :: flags ! options for the function selected. To use more than one OR them together e.g. OR(OPTION1, OPTION2)
|
||||
integer(4) :: execs_decrement ! amount by which to dec execs if we use flag: DEC_MANY_EXECS
|
||||
integer(4) :: data_crypt_key_num ! number of the key (1-3) that the dongle uses to encrypt or decrypt user data
|
||||
integer(4) :: rw_offset ! offset in the dongle data area to read or write data
|
||||
integer(4) :: rw_length ! length of data are to read/write/encrypt/decrypt
|
||||
integer(4) :: unused ! pass data by function parameter instead. 4 bytes long for 32-bit Fortran code.
|
||||
character(len=256) :: alt_licence_name ! protection check for different licence instead of the default one, must be null-terminated
|
||||
integer(4) :: var_a ! variable values for user algorithm
|
||||
integer(4) :: var_b
|
||||
integer(4) :: var_c
|
||||
integer(4) :: var_d
|
||||
integer(4) :: var_e
|
||||
integer(4) :: var_f
|
||||
integer(4) :: var_g
|
||||
integer(4) :: var_h
|
||||
integer(4) :: alg_number ! the number of the user algorithm that you want to execute
|
||||
|
||||
! outputs
|
||||
integer(4) :: ret_code ! return code from the protection check
|
||||
integer(4) :: ext_err ! extended error
|
||||
integer(4) :: type ! type of dongle detected. 1 = Pro, 2 = FD
|
||||
integer(4) :: model ! model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
|
||||
integer(4) :: sdsn ! Software Developer's Serial Number
|
||||
character(len=12) :: prodcode ! Product Code (null-terminated)
|
||||
integer(4) :: dongle_number ! NB this should be an unsigned value really
|
||||
integer(4) :: update_number
|
||||
integer(4) :: data_area_size ! size of the data area used in the dongle detected
|
||||
integer(4) :: max_alg_num ! the maximum algorithm number in the dongle detected
|
||||
integer(4) :: execs ! executions left: -1 indicates 'no limit'
|
||||
integer(4) :: exp_day ! expiry day: -1 indicates 'no limit'
|
||||
integer(4) :: exp_month ! expiry month: -1 indicates 'no limit'
|
||||
integer(4) :: exp_year ! expiry year: -1 indicates 'no limit'
|
||||
integer(4) :: features ! features value
|
||||
integer(4) :: net_users ! maximum number of network users for the dongle detected: -1 indicates 'no limit'
|
||||
integer(4) :: alg_answer ! answer to the user algorithm executed with the given variable values
|
||||
integer(4) :: fd_capacity ! capacity of the data area in FD dongle.
|
||||
character(len=128) :: fd_drive ! drive letter of FD dongle detected e.g. 'f:\' (or mount name under Linux)
|
||||
integer(4) :: swkey_type ! 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
|
||||
integer(4) :: swkey_exp_day ! software key expiry date (if software key detected)
|
||||
integer(4) :: swkey_exp_month
|
||||
integer(4) :: swkey_exp_year
|
||||
END TYPE DRIS
|
||||
|
||||
integer,parameter :: DRIS_SIZE = 560 ! I am sure there should be a way to get this programatically!
|
||||
|
||||
! functions - must specify only one
|
||||
integer,parameter :: PROTECTION_CHECK = 1 ! checks for dongle, check program params...
|
||||
integer,parameter :: EXECUTE_ALGORITHM = 2 ! protection check + calculate answer for specified algorithm with specified inputs
|
||||
integer,parameter :: WRITE_DATA_AREA = 3 ! protection check + writes dongle data area
|
||||
integer,parameter :: READ_DATA_AREA = 4 ! protection check + reads dongle data area
|
||||
integer,parameter :: ENCRYPT_USER_DATA = 5 ! protection check + the dongle will encrypt user data
|
||||
integer,parameter :: DECRYPT_USER_DATA = 6 ! protection check + the dongle will decrypt user data
|
||||
integer,parameter :: FAST_PRESENCE_CHECK = 7 ! checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
||||
integer,parameter :: STOP_NET_USER = 8 ! stops a network user (a protection check is NOT performed)
|
||||
|
||||
! flags - can specify as many as you like
|
||||
integer,parameter :: DEC_ONE_EXEC = 1 ! decrement execs by 1
|
||||
integer,parameter :: DEC_MANY_EXECS = 2 ! decrement execs by number specified in execs_decrement
|
||||
integer,parameter :: START_NET_USER = 4 ! starts a network user
|
||||
integer,parameter :: USE_FUNCTION_ARGUMENT = 16 ! use the extra argument in the function for pointers
|
||||
integer,parameter :: CHECK_LOCAL_FIRST = 32 ! always look in local ports before looking in network ports
|
||||
integer,parameter :: CHECK_NETWORK_FIRST = 64 ! always look on the network before looking in local ports
|
||||
integer,parameter :: USE_ALT_LICENCE_NAME = 128 ! use name specified in alt_licence_name instead of the default one
|
||||
integer,parameter :: DONT_SET_MAXDAYS_EXPIRY = 256 ! if the max days expiry date has not been calculated then do not do it this time
|
||||
integer,parameter :: MATCH_DONGLE_NUMBER = 512 ! restrict the search to match the dongle number specified in the DRIS
|
||||
integer,parameter :: DONT_RETURN_FD_DRIVE = 1024 ! if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
||||
|
||||
! this is an instance of the dris. We make an equivalence between the derived-type
|
||||
! and a byte_array because for encryption we need to access the memory as a byte array
|
||||
type (DRIS) :: mydris
|
||||
integer(1), dimension(DRIS_SIZE) :: mydris_byte_array
|
||||
equivalence(mydris, mydris_byte_array)
|
||||
|
||||
END MODULE DinkeyPro
|
||||
|
||||
! There is just the one function exported by dpwin32.dll
|
||||
MODULE DDFunctions
|
||||
use ISO_C_BINDING
|
||||
implicit none
|
||||
private
|
||||
|
||||
! declare the protection check function in the Dinkey Pro/FD runtime module
|
||||
public DDProtCheck
|
||||
INTERFACE
|
||||
FUNCTION DDProtCheck(my_dris, my_data) BIND (C, name="DDProtCheck")
|
||||
use iso_c_binding
|
||||
use DinkeyPro
|
||||
!GCC$ ATTRIBUTES STDCALL :: DDProtCheck
|
||||
integer(C_INT) DDProtCheck
|
||||
type (DRIS) my_dris
|
||||
character(kind=C_CHAR) my_data (*)
|
||||
END FUNCTION DDProtCheck
|
||||
END INTERFACE
|
||||
END MODULE DDFunctions
|
||||
|
||||
! ************************* our 10 functions **********************************
|
||||
|
||||
! ************************** ProtCheck ***************************************
|
||||
FUNCTION ProtCheck()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code
|
||||
integer(8) :: display_dongle_number
|
||||
|
||||
call set_random(mydris_byte_array) ! we have to call this function using the byte array equivalence of the dris type
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
ret_code = DDProtCheck(mydris, "dummy")
|
||||
ProtCheck = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! sample to show how to display dongle number (this is the only value in the dris that should be an unsigned integer)
|
||||
display_dongle_number = mydris%dongle_number
|
||||
call ConvertDongleNumber(display_dongle_number)
|
||||
print *,"Dongle Check successful. Dongle Number is: ",display_dongle_number
|
||||
END FUNCTION ProtCheck
|
||||
|
||||
! ************************** 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.
|
||||
FUNCTION MyAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyAlgorithm
|
||||
MyAlgorithm = a + b + c + d + e + f + g + h
|
||||
return
|
||||
END FUNCTION MyAlgorithm
|
||||
|
||||
! 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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code, my_alg_answer, a, b, c, d, e, f, g, h
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
ret_code = DDProtCheck(mydris, "dummy")
|
||||
ProtCheckWithAlg = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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
|
||||
a = mydris%var_a ! for some reason g95 does not execute MyAlgorithm correctly unless it is all on one line so you have to do stupid things like this
|
||||
b = mydris%var_b
|
||||
c = mydris%var_c
|
||||
d = mydris%var_d
|
||||
e = mydris%var_e
|
||||
f = mydris%var_f
|
||||
g = mydris%var_g
|
||||
h = mydris%var_h
|
||||
my_alg_answer = MyAlgorithm(a, b, c, d, e, f, g, h)
|
||||
if (my_alg_answer /= mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlg
|
||||
|
||||
! ************************** WriteBytes ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code
|
||||
character(len=14) :: WriteData = "Hello, World!"//CHAR(0) ! it should be a null-terminated string
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytes = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytes
|
||||
|
||||
! ************************** ReadBytes ***************************************
|
||||
! This reads 14 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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code
|
||||
character(len=14) :: ReadData
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytes = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytes
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code
|
||||
character(len=14) :: MyData = "Hello, World!"//CHAR(0)
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",MyData
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Decrypted data is: ",MyData
|
||||
END FUNCTION EncryptUserData
|
||||
|
||||
! !!!!!!!!!!! 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
|
||||
FUNCTION MyRWAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyAlgorithm
|
||||
MyRWAlgorithm = IEOR(IEOR(IEOR(IEOR(IEOR(a,b),c),d),e),f)
|
||||
return
|
||||
END FUNCTION MyRWAlgorithm
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
SUBROUTINE CryptDRIS(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer :: i,j,k,temp,t
|
||||
integer(1) :: temp2
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + 123, 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=17,DRIS_SIZE
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + 212, 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + 97,255) ! third parameter patched here
|
||||
temp2 = S(t+1)
|
||||
dris_byte_array(k) = IEOR(dris_byte_array(k),temp2)
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptDRIS
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
! if you are using the r/w algorithm then there is no need to change this function
|
||||
! NB we pass the whole of the DRIS but we only need it for seed1 and seed2 values
|
||||
SUBROUTINE CryptApiData(mydata, length, dris_byte_array, alg_answer)
|
||||
use DinkeyPro
|
||||
integer :: length, alg_answer, seed1, seed2
|
||||
integer(1), dimension(length) :: mydata
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer(1) :: temp2
|
||||
integer :: i,j,k,temp,t
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + IAND(alg_answer, 255), 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=1,length
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + IAND(ISHFT(alg_answer, -8),255), 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + IAND(ISHFT(alg_answer, -16),255),255) ! third parameter patched here
|
||||
temp2 = S(t+1)
|
||||
mydata(k) = IEOR(mydata(k),temp2)
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptApiData
|
||||
|
||||
! ************************** ProtCheckEnc ***************************************
|
||||
! We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ProtCheckEnc()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, "dummy")
|
||||
ProtCheckEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckEnc
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code, my_alg_answer, a, b, c, d, e, f, g, h
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, "dummy")
|
||||
ProtCheckWithAlgEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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
|
||||
a = mydris%var_a ! for some reason g95 does not execute MyAlgorithm correctly unless it is all on one line so you have to do stupid things like this
|
||||
b = mydris%var_b
|
||||
c = mydris%var_c
|
||||
d = mydris%var_d
|
||||
e = mydris%var_e
|
||||
f = mydris%var_f
|
||||
g = mydris%var_g
|
||||
h = mydris%var_h
|
||||
my_alg_answer = MyAlgorithm(a, b, c, d, e, f, g, h)
|
||||
if (my_alg_answer /= mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlgEnc
|
||||
|
||||
! ************************** WriteBytesEnc ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: WriteData = "Hello, World!"//CHAR(0)
|
||||
integer(1), dimension(14) :: WriteDataByteArray
|
||||
equivalence(WriteData, WriteDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g,&
|
||||
mydris%var_h)
|
||||
|
||||
! encrypt data we want to write.
|
||||
call CryptApiData(WriteDataByteArray, len(WriteData), mydris_byte_array, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytesEnc
|
||||
|
||||
! ************************** ReadBytesEnc ***************************************
|
||||
! This reads 14 bytes of data from offset 7 in the dongle data area
|
||||
! In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
||||
! In order for the data to be displayed properly by this routine it will need to be text data
|
||||
! We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ReadBytesEnc()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: ReadData
|
||||
integer(1), dimension(14) :: ReadDataByteArray
|
||||
equivalence(ReadData, ReadDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g,&
|
||||
mydris%var_h)
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! decrypt data we have just read.
|
||||
call CryptApiData(ReadDataByteArray, len(ReadData), mydris_byte_array, alg_ans);
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytesEnc
|
||||
|
||||
! ************************** EncryptUserDataEnc ***************************************
|
||||
! This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
||||
! It will then do another protection check & decrypt the data
|
||||
! We encrypt the DRIS and Data passed to/from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION EncryptUserDataEnc()
|
||||
use DinkeyPro
|
||||
use DDFunctions
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: MyData = "Hello, World!"//CHAR(0)
|
||||
integer(1), dimension(14) :: MyDataByteArray
|
||||
equivalence(MyData, MyDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g,&
|
||||
mydris%var_h)
|
||||
|
||||
! encrypt data we want to pass.
|
||||
call CryptApiData(MyDataByteArray, len(MyData), mydris_byte_array, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",MyData
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g,&
|
||||
mydris%var_h)
|
||||
! decrypt data that was passed to us by the API.
|
||||
call CryptApiData(MyDataByteArray, len(MyData), mydris_byte_array, alg_ans);
|
||||
print *,"Decrypted data is: ",MyData
|
||||
END FUNCTION EncryptUserDataEnc
|
||||
|
||||
! ************************** useful subroutines *******************************
|
||||
! subroutine to randomise each element of the DRIS (expects you to pass the DRIS as a byte array
|
||||
SUBROUTINE set_random(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
real,dimension(DRIS_SIZE) :: temp
|
||||
|
||||
call random_seed()
|
||||
call random_number(temp)
|
||||
do i=1,DRIS_SIZE
|
||||
dris_byte_array(i) = temp(i)*256
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE set_random
|
||||
|
||||
! subroutine to convert an unsigned integer (stored as a signed integer) to the correct unsigned value (for display purposes)
|
||||
! e.g. the dongle_number value in the dris - should be an unsigned integer but Fortran 90 does not support them
|
||||
SUBROUTINE ConvertDongleNumber(value)
|
||||
integer(8) :: value
|
||||
|
||||
if (value < 0) then
|
||||
value = value + 4294967296 _8 ! make the -ve value a +ve value
|
||||
end if
|
||||
return
|
||||
END SUBROUTINE ConvertDongleNumber
|
||||
|
||||
! displays messages for the most common errors. You will want to change this for your code
|
||||
SUBROUTINE DisplayError(ret_code, extended_error)
|
||||
integer :: ret_code, extended_error
|
||||
|
||||
select case (ret_code)
|
||||
case (401)
|
||||
print *,"Error! No dongles detected!"
|
||||
case (403)
|
||||
print *,"Error! The dongle detected has a different type to the one specified in DinkeyAdd."
|
||||
case (404)
|
||||
print *,"Error! The dongle detected has a different model to those specified in DinkeyAdd."
|
||||
case (409)
|
||||
print *,"Error! The dongle detected has not been programmed by DinkeyAdd."
|
||||
case (410)
|
||||
print *,"Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd."
|
||||
case (411)
|
||||
print *,"Error! The dongle detected does not contain the licence associated with this program."
|
||||
case (413)
|
||||
print *,"Error! This program has not been protected by DinkeyAdd."
|
||||
print *,"For guidance please read the DinkeyAdd chapter of the Dinkey manual."
|
||||
case (417)
|
||||
print *,"Error! One or more of the parameters set in the DRIS is incorrect. This could be caused if you are encrypting the"
|
||||
print *," DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa."
|
||||
case (423)
|
||||
print *,"Error! The number of network users has been exceeded."
|
||||
case (435)
|
||||
print *,"Error! DinkeyServer has not been detected on the network."
|
||||
case (922)
|
||||
print *,"Error! The Software Key has expired."
|
||||
case default
|
||||
print *,"An error occurred checking the dongle. Error: ", ret_code, " Extended Error: ", extended_error
|
||||
end select
|
||||
return
|
||||
END SUBROUTINE DisplayError
|
||||
26
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/iDllTest.sln
Normal file
26
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/iDllTest.sln
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "iDllTest", "iDllTest.vfproj", "{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Debug|x64.Build.0 = Debug|x64
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Release|Win32.Build.0 = Release|Win32
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Release|x64.ActiveCfg = Release|x64
|
||||
{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
52
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/iDllTest.vfproj
Normal file
52
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/iDllTest.vfproj
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<VisualStudioProject ProjectCreator="Intel Fortran" Keyword="Console Application" Version="11.0" ProjectIdGuid="{99DA52B5-1568-4A3F-B7D1-CD1813A2CF94}">
|
||||
<Platforms>
|
||||
<Platform Name="Win32"/>
|
||||
<Platform Name="x64"/></Platforms>
|
||||
<Configurations>
|
||||
<Configuration Name="Debug|Win32">
|
||||
<Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Interfaces="true" WarnInterfaces="true" Traceback="true" BoundsCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/>
|
||||
<Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemConsole" AdditionalDependencies="..\..\C\import_libs\dpwin32.lib"/>
|
||||
<Tool Name="VFResourceCompilerTool"/>
|
||||
<Tool Name="VFMidlTool" SuppressStartupBanner="true"/>
|
||||
<Tool Name="VFCustomBuildTool"/>
|
||||
<Tool Name="VFPreLinkEventTool"/>
|
||||
<Tool Name="VFPreBuildEventTool"/>
|
||||
<Tool Name="VFPostBuildEventTool"/>
|
||||
<Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration>
|
||||
<Configuration Name="Release|Win32">
|
||||
<Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true"/>
|
||||
<Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" SubSystem="subSystemConsole" AdditionalDependencies="..\..\C\import_libs\dpwin32.lib"/>
|
||||
<Tool Name="VFResourceCompilerTool"/>
|
||||
<Tool Name="VFMidlTool" SuppressStartupBanner="true"/>
|
||||
<Tool Name="VFCustomBuildTool"/>
|
||||
<Tool Name="VFPreLinkEventTool"/>
|
||||
<Tool Name="VFPreBuildEventTool"/>
|
||||
<Tool Name="VFPostBuildEventTool"/>
|
||||
<Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration>
|
||||
<Configuration Name="Debug|x64">
|
||||
<Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true" DebugInformationFormat="debugEnabled" Optimization="optimizeDisabled" Interfaces="true" WarnInterfaces="true" Traceback="true" BoundsCheck="true" RuntimeLibrary="rtMultiThreadedDebug"/>
|
||||
<Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" GenerateDebugInformation="true" SubSystem="subSystemConsole" AdditionalDependencies="..\..\C\import_libs\dpwin64.lib"/>
|
||||
<Tool Name="VFResourceCompilerTool"/>
|
||||
<Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/>
|
||||
<Tool Name="VFCustomBuildTool"/>
|
||||
<Tool Name="VFPreLinkEventTool"/>
|
||||
<Tool Name="VFPreBuildEventTool"/>
|
||||
<Tool Name="VFPostBuildEventTool"/>
|
||||
<Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration>
|
||||
<Configuration Name="Release|x64">
|
||||
<Tool Name="VFFortranCompilerTool" SuppressStartupBanner="true"/>
|
||||
<Tool Name="VFLinkerTool" LinkIncremental="linkIncrementalNo" SuppressStartupBanner="true" SubSystem="subSystemConsole" AdditionalDependencies="..\..\C\import_libs\dpwin64.lib"/>
|
||||
<Tool Name="VFResourceCompilerTool"/>
|
||||
<Tool Name="VFMidlTool" SuppressStartupBanner="true" TargetEnvironment="midlTargetAMD64"/>
|
||||
<Tool Name="VFCustomBuildTool"/>
|
||||
<Tool Name="VFPreLinkEventTool"/>
|
||||
<Tool Name="VFPreBuildEventTool"/>
|
||||
<Tool Name="VFPostBuildEventTool"/>
|
||||
<Tool Name="VFManifestTool" SuppressStartupBanner="true"/></Configuration></Configurations>
|
||||
<Files>
|
||||
<Filter Name="Header Files" Filter="fi;fd"/>
|
||||
<Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"/>
|
||||
<Filter Name="Source Files" Filter="f90;for;f;fpp;ftn;def;odl;idl">
|
||||
<File RelativePath=".\idlltest.f90"/></Filter></Files>
|
||||
<Globals/></VisualStudioProject>
|
||||
826
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/idlltest.f90
Normal file
826
Dinkey Pro 7.6.1/Samples/Fortran/Runtime/idlltest.f90
Normal file
@@ -0,0 +1,826 @@
|
||||
! dlltest - sample program to call DinkeyPro/FD runtime module (dpwin32.dll)
|
||||
!
|
||||
! this sample code has been compiled and tested using Intel Fortran XE 2011
|
||||
! but should work with earlier versions.
|
||||
|
||||
! The sample code contains 10 functions. You will not need to use all these
|
||||
! functions in your code. Just use which ever functions are most appropriate
|
||||
! and customise in your own way. The sample code is just a guide. You should
|
||||
! implement the protection in a stronger way using the techniques described in
|
||||
! the "Increasing your Protection" chapter of the manual.
|
||||
|
||||
!If you are using Dinkey Lite then you can only use 4 functions:
|
||||
!ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
||||
|
||||
! this file contains 10 protection-check functions.
|
||||
! ProtCheck a standard protection check
|
||||
! ProtCheckWithAlg a protection check & executing an algorithm
|
||||
! WriteBytes a protection check & write data to the dongle
|
||||
! ReadBytes a protection check & read data from the dongle
|
||||
! EncryptUserData a protection check & encrypting data and then decrypting the data
|
||||
! these functions are the same as the functions listed above but encrypting all parameters passed to our API
|
||||
! ProtCheckEnc a standard protection check
|
||||
! ProtCheckWithAlgEnc a protection check & executing an Algorithm
|
||||
! WriteBytesEnc a protection check & write data to the dongle
|
||||
! ReadBytesEnc a protection check & read data from the dongle
|
||||
! EncryptUserDataEnc a protection check & encrypting data and then decrypting the data
|
||||
|
||||
PROGRAM main
|
||||
! call the function(s) of your choice here
|
||||
! by default I have chosen a standard protection check
|
||||
if (ProtCheck() == 0) then
|
||||
print *,"It worked!"
|
||||
end if
|
||||
END PROGRAM main
|
||||
|
||||
! this module contains the DRIS structure declaration and also declares important constants
|
||||
MODULE DinkeyPro
|
||||
|
||||
integer,parameter :: MY_SDSN = 10101 !!!! change this value to be the value of your SDSN (demo = 10101)
|
||||
|
||||
! declare dris data type
|
||||
!DEC$ PACK:1 ! this needs to be byte aligned
|
||||
TYPE DRIS
|
||||
sequence
|
||||
! the first 4 fields are never encrypted
|
||||
character(len=4) :: header ! should be set to 'DRIS'
|
||||
! inputs
|
||||
integer(4) :: size ! size of this structure
|
||||
integer(4) :: seed1 ! seed for data/dris encryption
|
||||
integer(4) :: seed2 ! as above
|
||||
! (maybe encrypted from now on)
|
||||
integer(4) :: function ! specify only one function
|
||||
integer(4) :: flags ! options for the function selected. To use more than one OR them together e.g. OR(OPTION1, OPTION2)
|
||||
integer(4) :: execs_decrement ! amount by which to dec execs if we use flag: DEC_MANY_EXECS
|
||||
integer(4) :: data_crypt_key_num ! number of the key (1-3) that the dongle uses to encrypt or decrypt user data
|
||||
integer(4) :: rw_offset ! offset in the dongle data area to read or write data
|
||||
integer(4) :: rw_length ! length of data are to read/write/encrypt/decrypt
|
||||
!DEC$ IF DEFINED (_M_X64)
|
||||
integer(8) :: unused ! pass data by function parameter instead. 8 bytes long for 64-bit Fortran code.
|
||||
!DEC$ ELSE
|
||||
integer(4) :: unused ! pass data by function parameter instead. 4 bytes long for 32-bit Fortran code.
|
||||
!DEC$ ENDIF
|
||||
character(len=256) :: alt_licence_name ! protection check for different licence instead of the default one, must be null-terminated
|
||||
integer(4) :: var_a ! variable values for user algorithm
|
||||
integer(4) :: var_b
|
||||
integer(4) :: var_c
|
||||
integer(4) :: var_d
|
||||
integer(4) :: var_e
|
||||
integer(4) :: var_f
|
||||
integer(4) :: var_g
|
||||
integer(4) :: var_h
|
||||
integer(4) :: alg_number ! the number of the user algorithm that you want to execute
|
||||
|
||||
! outputs
|
||||
integer(4) :: ret_code ! return code from the protection check
|
||||
integer(4) :: ext_err ! extended error
|
||||
integer(4) :: type ! type of dongle detected. 1 = Pro, 2 = FD
|
||||
integer(4) :: model ! model of dongle detected. 1= Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
|
||||
integer(4) :: sdsn ! Software Developer's Serial Number
|
||||
character(len=12) :: prodcode ! Product Code (null-terminated)
|
||||
integer(4) :: dongle_number ! NB this should be an unsigned value really
|
||||
integer(4) :: update_number
|
||||
integer(4) :: data_area_size ! size of the data area used in the dongle detected
|
||||
integer(4) :: max_alg_num ! the maximum algorithm number in the dongle detected
|
||||
integer(4) :: execs ! executions left: -1 indicates 'no limit'
|
||||
integer(4) :: exp_day ! expiry day: -1 indicates 'no limit'
|
||||
integer(4) :: exp_month ! expiry month: -1 indicates 'no limit'
|
||||
integer(4) :: exp_year ! expiry year: -1 indicates 'no limit'
|
||||
integer(4) :: features ! features value
|
||||
integer(4) :: net_users ! maximum number of network users for the dongle detected: -1 indicates 'no limit'
|
||||
integer(4) :: alg_answer ! answer to the user algorithm executed with the given variable values
|
||||
integer(4) :: fd_capacity ! capacity of the data area in FD dongle.
|
||||
character(len=128) :: fd_drive ! drive letter of FD dongle detected e.g. 'f:\' (or mount name under Linux)
|
||||
integer(4) :: swkey_type ! 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
|
||||
integer(4) :: swkey_exp_day ! software key expiry date (if software key detected)
|
||||
integer(4) :: swkey_exp_month
|
||||
integer(4) :: swkey_exp_year
|
||||
END TYPE DRIS
|
||||
!DEC$ PACK
|
||||
|
||||
!DEC$ IF DEFINED (_M_X64)
|
||||
integer,parameter :: DRIS_SIZE = 564 ! I am sure there should be a way to get this programatically!
|
||||
!DEC$ ELSE
|
||||
integer,parameter :: DRIS_SIZE = 560 ! I am sure there should be a way to get this programatically!
|
||||
!DEC$ ENDIF
|
||||
|
||||
! functions - must specify only one
|
||||
integer,parameter :: PROTECTION_CHECK = 1 ! checks for dongle, check program params...
|
||||
integer,parameter :: EXECUTE_ALGORITHM = 2 ! protection check + calculate answer for specified algorithm with specified inputs
|
||||
integer,parameter :: WRITE_DATA_AREA = 3 ! protection check + writes dongle data area
|
||||
integer,parameter :: READ_DATA_AREA = 4 ! protection check + reads dongle data area
|
||||
integer,parameter :: ENCRYPT_USER_DATA = 5 ! protection check + the dongle will encrypt user data
|
||||
integer,parameter :: DECRYPT_USER_DATA = 6 ! protection check + the dongle will decrypt user data
|
||||
integer,parameter :: FAST_PRESENCE_CHECK = 7 ! checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
||||
integer,parameter :: STOP_NET_USER = 8 ! stops a network user (a protection check is NOT performed)
|
||||
|
||||
! flags - can specify as many as you like
|
||||
integer,parameter :: DEC_ONE_EXEC = 1 ! decrement execs by 1
|
||||
integer,parameter :: DEC_MANY_EXECS = 2 ! decrement execs by number specified in execs_decrement
|
||||
integer,parameter :: START_NET_USER = 4 ! starts a network user
|
||||
integer,parameter :: USE_FUNCTION_ARGUMENT = 16 ! use the extra argument in the function for pointers
|
||||
integer,parameter :: CHECK_LOCAL_FIRST = 32 ! always look in local ports before looking in network ports
|
||||
integer,parameter :: CHECK_NETWORK_FIRST = 64 ! always look on the network before looking in local ports
|
||||
integer,parameter :: USE_ALT_LICENCE_NAME = 128 ! use name specified in alt_licence_name instead of the default one
|
||||
integer,parameter :: DONT_SET_MAXDAYS_EXPIRY = 256 ! if the max days expiry date has not been calculated then do not do it this time
|
||||
integer,parameter :: MATCH_DONGLE_NUMBER = 512 ! restrict the search to match the dongle number specified in the DRIS
|
||||
integer,parameter :: DONT_RETURN_FD_DRIVE = 1024 ! if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
||||
|
||||
! declare the protection check function in the Dinkey Pro/FD runtime module
|
||||
INTERFACE
|
||||
FUNCTION DDProtCheck(mydris, mydata)
|
||||
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:'DDProtCheck', DLLIMPORT :: DDProtCheck
|
||||
import
|
||||
type (DRIS) :: mydris
|
||||
!DEC$ ATTRIBUTES REFERENCE :: mydris
|
||||
character(len=*) :: mydata
|
||||
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: mydata
|
||||
integer :: DDProtCheck
|
||||
END FUNCTION DDProtCheck
|
||||
END INTERFACE
|
||||
|
||||
! this is an instance of the dris. We make an equivalence between the derived-type
|
||||
! and a byte_array because for encryption we need to access the memory as a byte array
|
||||
type (DRIS) :: mydris
|
||||
integer(1), dimension(DRIS_SIZE) :: mydris_byte_array
|
||||
equivalence(mydris, mydris_byte_array)
|
||||
|
||||
END MODULE DinkeyPro
|
||||
|
||||
! ************************* our 10 functions **********************************
|
||||
|
||||
! ************************** ProtCheck ***************************************
|
||||
FUNCTION ProtCheck()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
integer(8) :: display_dongle_number
|
||||
|
||||
call set_random(mydris_byte_array) ! we have to call this function using the byte array equivalence of the dris type
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheck = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheck = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! sample to show how to display dongle number (this is the only value in the dris that should be an unsigned integer)
|
||||
display_dongle_number = mydris%dongle_number
|
||||
call ConvertDongleNumber(display_dongle_number)
|
||||
print *,"Dongle Check successful. Dongle Number is: ",display_dongle_number
|
||||
END FUNCTION ProtCheck
|
||||
|
||||
! ************************** 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.
|
||||
FUNCTION MyAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyAlgorithm
|
||||
MyAlgorithm = a + b + c + d + e + f + g + h
|
||||
return
|
||||
END FUNCTION MyAlgorithm
|
||||
|
||||
! 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckWithAlg = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h) /= mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlg = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlg
|
||||
|
||||
! ************************** WriteBytes ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=14) :: WriteData = "Hello, World!"c ! it should be a null-terminated string
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytes = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytes = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytes
|
||||
|
||||
! ************************** ReadBytes ***************************************
|
||||
! This reads 14 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=14) :: ReadData
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytes = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytes = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytes
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
character(len=14) :: MyData = "Hello, World!"c
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",MyData
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserData = ret_code
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserData = -1
|
||||
return
|
||||
end if
|
||||
|
||||
print *,"Decrypted data is: ",MyData
|
||||
END FUNCTION EncryptUserData
|
||||
|
||||
! !!!!!!!!!!! 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
|
||||
FUNCTION MyRWAlgorithm(a, b, c, d, e, f, g, h)
|
||||
integer :: a,b,c,d,e,f,g,h,MyRWAlgorithm
|
||||
MyRWAlgorithm = IEOR(IEOR(IEOR(IEOR(IEOR(a,b),c),d),e),f)
|
||||
return
|
||||
END FUNCTION MyRWAlgorithm
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
SUBROUTINE CryptDRIS(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer :: i,j,k,temp,t
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + 123, 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=17,DRIS_SIZE
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + 212, 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + 97,255) ! third parameter patched here
|
||||
dris_byte_array(k) = IEOR(dris_byte_array(k),S(t+1))
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptDRIS
|
||||
|
||||
! !!!! please patch the 3 parameters specified below with the 3 parameters specified in DinkeyAdd
|
||||
! if you are using the r/w algorithm then there is no need to change this function
|
||||
! NB we pass the whole of the DRIS but we only need it for seed1 and seed2 values
|
||||
SUBROUTINE CryptApiData(mydata, length, dris_byte_array, alg_answer)
|
||||
use DinkeyPro
|
||||
integer :: length, alg_answer, seed1, seed2
|
||||
integer(1), dimension(length) :: mydata
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
integer :: i,j,k,temp,t
|
||||
integer, dimension(256) :: bigseed,S
|
||||
|
||||
do i=1,256
|
||||
bigseed(i) = dris_byte_array(9 + modulo(i-1,8)) ! this takes the values from seed1, seed2 directly
|
||||
end do
|
||||
|
||||
do i=1,256
|
||||
S(i) = i-1
|
||||
end do
|
||||
|
||||
j = 0
|
||||
do i=1,256
|
||||
j = IAND(j + S(i) + bigseed(i) + IAND(alg_answer, 255), 255) ! first parameter patched here
|
||||
temp = S(i)
|
||||
S(i) = S(j+1)
|
||||
S(j+1) = temp
|
||||
end do
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
do k=1,length
|
||||
i = IAND(i + 1, 255)
|
||||
j = IAND(j + S(i+1) + IAND(ISHFT(alg_answer, -8),255), 255) ! second parameter patched here
|
||||
temp = S(i+1)
|
||||
S(i+1) = S(j+1)
|
||||
S(j+1) = temp
|
||||
t = IAND(S(i+1) + S(j+1) + IAND(ISHFT(alg_answer, -16),255),255) ! third parameter patched here
|
||||
mydata(k) = IEOR(mydata(k),S(t+1))
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE CryptApiData
|
||||
|
||||
! ************************** ProtCheckEnc ***************************************
|
||||
! We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ProtCheckEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = PROTECTION_CHECK ! standard protection check
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckEnc
|
||||
|
||||
! ************************** 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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = EXECUTE_ALGORITHM ! standard protection check & execute algorithm
|
||||
mydris%flags = 0 ! no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
|
||||
mydris%alg_number = 1 ! execute algorithm 1 (you do not need to specify this field if you are only using Lite models).
|
||||
! you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
|
||||
mydris%var_a = 1 ! sample values
|
||||
mydris%var_b = 2
|
||||
mydris%var_c = 3
|
||||
mydris%var_d = 4
|
||||
mydris%var_e = 5
|
||||
mydris%var_f = 6
|
||||
mydris%var_g = 7
|
||||
mydris%var_h = 8
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, 0)
|
||||
ProtCheckWithAlgEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! 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(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h) /= mydris%alg_answer) then
|
||||
print *,"Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine"
|
||||
ProtCheckWithAlgEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION ProtCheckWithAlgEnc
|
||||
|
||||
! ************************** WriteBytesEnc ***************************************
|
||||
! This writes the Data "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()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: WriteData = "Hello, World!"c
|
||||
integer(1), dimension(14) :: WriteDataByteArray
|
||||
equivalence(WriteData, WriteDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = WRITE_DATA_AREA ! standard protection check and write data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(WriteData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
! encrypt data we want to write.
|
||||
call CryptApiData(WriteDataByteArray, len(WriteData), mydris_byte_array, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, WriteData)
|
||||
WriteBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
WriteBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
END FUNCTION WriteBytesEnc
|
||||
|
||||
! ************************** ReadBytesEnc ***************************************
|
||||
! This reads 14 bytes of data from offset 7 in the dongle data area
|
||||
! In order for this function to work you will need to have a data area in your dongle that is at least 21 bytes long.
|
||||
! In order for the data to be displayed properly by this routine it will need to be text data
|
||||
! We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION ReadBytesEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: ReadData
|
||||
integer(1), dimension(14) :: ReadDataByteArray
|
||||
equivalence(ReadData, ReadDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = READ_DATA_AREA ! standard protection check and read data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%rw_offset = 7
|
||||
mydris%rw_length = len(ReadData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, ReadData)
|
||||
ReadBytesEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
ReadBytesEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! decrypt data we have just read.
|
||||
call CryptApiData(ReadDataByteArray, len(ReadData), mydris_byte_array, alg_ans);
|
||||
print *,"Dinkey Dongle Data area, offset 7 is: ",ReadData
|
||||
END FUNCTION ReadBytesEnc
|
||||
|
||||
! ************************** EncryptUserDataEnc ***************************************
|
||||
! This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
|
||||
! It will then do another protection check & decrypt the data
|
||||
! We encrypt the DRIS and Data passed to/from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
|
||||
FUNCTION EncryptUserDataEnc()
|
||||
use DinkeyPro
|
||||
integer :: ret_code,alg_ans
|
||||
character(len=14) :: MyData = "Hello, World!"c
|
||||
integer(1), dimension(14) :: MyDataByteArray
|
||||
equivalence(MyData, MyDataByteArray) ! to encrypt it we need to pass it as a byte array
|
||||
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = ENCRYPT_USER_DATA ! standard protection check and encrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
! calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
|
||||
! encrypt data we want to pass.
|
||||
call CryptApiData(MyDataByteArray, len(MyData), mydris_byte_array, alg_ans);
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
! ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
|
||||
|
||||
print *,"Encrypted data is: ",MyData
|
||||
|
||||
! Now decrypt the same data to get the original values
|
||||
call set_random(mydris_byte_array)
|
||||
mydris%header = 'DRIS'
|
||||
mydris%size = DRIS_SIZE
|
||||
mydris%function = DECRYPT_USER_DATA ! standard protection check and decrypt user data
|
||||
mydris%flags = USE_FUNCTION_ARGUMENT ! this way we don't need to worry about pointers in the DRIS
|
||||
mydris%data_crypt_key_num = 1
|
||||
mydris%rw_length = len(MyData)
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
ret_code = DDProtCheck(mydris, MyData)
|
||||
EncryptUserDataEnc = ret_code
|
||||
|
||||
call CryptDRIS(mydris_byte_array) ! decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
|
||||
|
||||
if (ret_code /= 0) then
|
||||
call DisplayError(ret_code, mydris%ext_err) ! display messages for any errors that have occurred
|
||||
return
|
||||
end if
|
||||
|
||||
if (mydris%sdsn /= MY_SDSN) then
|
||||
print *,"Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
! later on in your program you can check the return code again
|
||||
if (mydris%ret_code /= 0) then
|
||||
print *,"Dinkey Dongle protection error."
|
||||
EncryptUserDataEnc = -1
|
||||
return
|
||||
end if
|
||||
|
||||
alg_ans = MyRWAlgorithm(mydris%var_a, mydris%var_b, mydris%var_c, mydris%var_d, mydris%var_e, mydris%var_f, mydris%var_g, mydris%var_h)
|
||||
! decrypt data that was passed to us by the API.
|
||||
call CryptApiData(MyDataByteArray, len(MyData), mydris_byte_array, alg_ans);
|
||||
print *,"Decrypted data is: ",MyData
|
||||
END FUNCTION EncryptUserDataEnc
|
||||
|
||||
! ************************** useful subroutines *******************************
|
||||
! subroutine to randomise each element of the DRIS (expects you to pass the DRIS as a byte array
|
||||
SUBROUTINE set_random(dris_byte_array)
|
||||
use DinkeyPro
|
||||
integer(1), dimension(DRIS_SIZE) :: dris_byte_array
|
||||
real,dimension(DRIS_SIZE) :: temp
|
||||
|
||||
call random_seed()
|
||||
call random_number(temp)
|
||||
do i=1,DRIS_SIZE
|
||||
dris_byte_array(i) = temp(i)*256
|
||||
end do
|
||||
return
|
||||
END SUBROUTINE set_random
|
||||
|
||||
! subroutine to convert an unsigned integer (stored as a signed integer) to the correct unsigned value (for display purposes)
|
||||
! e.g. the dongle_number value in the dris - should be an unsigned integer but Fortran 90 does not support them
|
||||
SUBROUTINE ConvertDongleNumber(value)
|
||||
integer(8) :: value
|
||||
|
||||
if (value < 0) then
|
||||
value = value + 4294967296 ! make the -ve value a +ve value
|
||||
end if
|
||||
return
|
||||
END SUBROUTINE ConvertDongleNumber
|
||||
|
||||
! displays messages for the most common errors. You will want to change this for your code
|
||||
SUBROUTINE DisplayError(ret_code, extended_error)
|
||||
integer :: ret_code, extended_error
|
||||
|
||||
select case (ret_code)
|
||||
case (401)
|
||||
print *,"Error! No dongles detected!"
|
||||
case (403)
|
||||
print *,"Error! The dongle detected has a different type to the one specified in DinkeyAdd."
|
||||
case (404)
|
||||
print *,"Error! The dongle detected has a different model to those specified in DinkeyAdd."
|
||||
case (409)
|
||||
print *,"Error! The dongle detected has not been programmed by DinkeyAdd."
|
||||
case (410)
|
||||
print *,"Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd."
|
||||
case (411)
|
||||
print *,"Error! The dongle detected does not contain the licence associated with this program."
|
||||
case (413)
|
||||
print *,"Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual."
|
||||
case (417)
|
||||
print *,"Error! One or more of the parameters set in the DRIS is incorrect. This could be caused if you are encrypting the DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa."
|
||||
case (423)
|
||||
print *,"Error! The number of network users has been exceeded."
|
||||
case (435)
|
||||
print *,"Error! DinkeyServer has not been detected on the network."
|
||||
case (922)
|
||||
print *,"Error! The Software Key has expired."
|
||||
case default
|
||||
print *,"An error occurred checking the dongle. Error: ", ret_code, " Extended Error: ", extended_error
|
||||
end select
|
||||
return
|
||||
END SUBROUTINE DisplayError
|
||||
Reference in New Issue
Block a user