Chapter Six -- API Application Examples
We will take the interface of the C language to demonstrate how to call the API. Similarly, you may call other language interfaces by the same way. FEITIAN offers several program examples to help beginners quickly familiarize themselves with Rockey4ND. These sample programs are intentionally simplified to illustrate various security objectives and should not be construed as sufficient for most real world implementations. These samples are for demonstration purposes only. This document is not intended to illustrate how to take full advantage of the Rockey4ND software protection system – that will depend on particularities of the developer, the application and the licensing objectives. Advanced Application Examples are also a good reference but the developer will need to determine the best protection method given his own constraints and objectives. Some key points that you need to pay attention to when programming: 1) P3 and P4 are Advanced passwords enabling the developers to write to the dongles. They should not appear in software delivered to end users. 2) Be sure that none of the address parameters in the ROCKET4 functions are Null pointers. For example, even if you do not require the Buffer, but it cannot be null, otherwise the result is unpredictable. The following sample programs are written in Linux. Let us discuss how to perform the required functions step by step from an original program. Software developers who develop software in other languages please do not skip this section. There are no special developing skills for the C language. Most software developers will understand the concepts illustrated here. Note: We demonstrate the API under the directory "ROCKEY4ND/test". Step1. Write API in test.c : Step2. After writing API, you can compile source programe by the file named Makefile: Step3. All is ok, we can compile and run the file named test. Then, Let's discuss API interface program in detail. 1.Basic Application Examples 1.1)Find a Rockey4ND–Step 1 We add an operation to find the Rockey4ND at the beginning of the program. If the dongle is found the program will continue. If it is not found the program will exit. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { //=================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn’t Password 3, Set to 0 p4 = 0; // Program needn’t Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } printf("Hello FEITIAN!\n"); } It is a very simple security objective. We only need to call the function “Find a Rockey4ND dongle”. You may refer to the introduction of the function “Find a Rockey4ND dongle” in the section “Chapter Five -- Rockey4ND API”. For testing purposes you might try to run this program with and without the Rockey4ND dongle attached to the computer. 1.2)Open the Rockey4ND–Step 2 We add an operation to open Rockey4ND with specified passwords at the beginning of the program. If the dongle is opened the program continues. If not the program exits. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // ======================================================= WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found {printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error {printf("Error Code: %d\n", retcode); return; } printf("Hello FEITIAN!\n"); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.3)Initialize Rockey4ND with Editor or API. Write “Hello FEITIAN!” to the dongle and read it back from the dongle. See Step 3 and Step 4. Initialize Rockey4ND and write “Hello FEITIAN!” to it – Step 3: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // ==================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2= 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } p1 = 0; // Pos p2 = 14; // Length strcpy((char*)buffer, "Hello FEITIAN! "); retcode = Rockey(RY_WRITE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Write: %s\n", buffer); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } In Step 3 we have written “Hello FEITIAN!” to the Rockey4ND dongle. In Step 4 we will read the contents of the dongle. Read dongle contents – Step 4: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // ========================================================= WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return;} retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } p1 = 0; // Pos p2 = 14; // Length buffer[14] = 0; retcode = Rockey(RY_READ, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } // ============================================================= printf("%s\n", buffer); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.4)Generate a true random number with Rockey4ND – Step 5 Generate a random number when the program starts and write this random number to the dongle. The program should check if the random number is correct during run-time. If a sharing device is installed to this computer, and someone else runs this program also from another computer, another random number will be generated and written to the dongle. Thus the program on the first computer will be terminated since the random number is not correct. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // =========================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } retcode = Rockey(RY_RANDOM, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Random:%04X\n", p1); sprintf(buffer, "%04X", p1); p1 = 0; // Pos p2 = 4; // Length retcode = Rockey(RY_WRITE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Write: %s\n", buffer); p1 = 0; // Pos p2 = 4; // Length buffer[4] = 0; retcode = Rockey(RY_READ, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Read: %s\n", buffer); if(buffer) printf("Hello FEITIAN!\n"); else exit(0); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.5. Read the seed code return values with the Editor or API. The seed code calculation is performed inside the dongle and the algorithm is confidential. You may verify the return codes or use the return codes in an encryption routine. See Step 6 and Step 7. Read the return codes of fixed seed code (0x12345678), Step 6: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } //seed Rockey lp2 = 0x12345678; retcode = Rockey(RY_SEED, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); // Close Rockey retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } printf("\n"); getch(); } Verify the return codes of the seed code to see if the program should be terminated, see Step 7: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } //seed Rockey lp2 = 0x12345678; retcode = Rockey(RY_SEED, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } if (p1==0xD03A && p2==0x94D6 && p3==0x96A9 && p4==0x7F54) printf("Hello FEITIAN!\n"); else { printf("Hello error!\n"); return; } // Close Rockey retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.6. Write the User ID to the dongle with the Editor or API. User ID may be a software version or product type and it may also be used in some encryption schemes. See Step 8 and Step 9. Note: Advanced passwords are needed for Step 8. Initialize Rockey4ND and write User ID to the dongle. See Step 8: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // ============================================================= WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0x0799; // Rockey Demo Password 3 p4 = 0xc43b; // Rockey Demo Password 4 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } lp1 = 0x88888888; retcode = Rockey(RY_WRITE_USERID, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Write User ID: %08X\n", lp1); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } Verify the User ID. If the User ID is not 0x88888888 output “Hello DEMO!”. See Step 9: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // =========================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle,&lp1, &lp2, &p1, &p2, &p3,&p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } lp1 = 0; retcode=Rockey(RY_READ_USERID,&handle,&lp1,&lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } if (lp1= =0x88888888) printf("Hello FEITIAN!\n"); else { printf("Hello DEMO!\n"); return; } retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.7. Set module value and attributes with Editor or API then check if the module is allowed to be used. Determine whether to activate the associated application module. The module value may also be used by the program. Check if the module is allowed to be decreased to limit the number of software executions. See Step 10, Step 11 and Step 12. Note: Advanced passwords are needed for Step 10. Initialize Rockey4ND and set module value. For example we set module 0 to be valid and its value cannot be decreased. See Step 10: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // =========================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0x0799; // Rockey Demo Password 3 p4 = 0xc43b; // Rockey Demo Password 4 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } p1 = 0; p2 = 3; p3 = 0; retcode = Rockey(RY_SET_MOUDLE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } printf("Set Module 0: Pass = %04X Decrease no allow\n”,P2); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } If module 0 is valid in the program, output “Hello FEITIAN!”. Otherwise terminate or exit the program. See Step 11: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { // ============================================================ WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } p1 = 0; retcode = Rockey(RY_CHECK_MOUDLE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } if (p2) printf("Hello FEITIAN!\n"); else return; retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } In Step 10 we set p2=3(allowed software run times) and p3=1(Decrement allowed). That is to say module 0(p1=0) sets the maximum software run time to 3. See Step 12: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() {// ============================================================== WORD retcode; WORD handle, p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find specified Rockey retcode = Rockey(RY_FIND, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Not found { printf("ROCKEY not found!\n"); return; } retcode = Rockey(RY_OPEN, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } p1 = 0; retcode = Rockey(RY_CHECK_MOUDLE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } if (p2!=1) { printf("Update Please!\n"); return; } if(p3==1) { p1=0; retcode = Rockey(RY_DECREASE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if(retcode) { printf("Error Code: %d\n", retcode); return; } } printf("Hello FEITIAN!\n"); retcode = Rockey(RY_CLOSE, &handle, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } 1.8). Multi Rockey4ND dongles with the same passwords may work on the same computer no matter whether the dongle types are the same or not. The program can distinguish the dongles because every dongle has a unique hardware ID. See Step 13: #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { int i, rynum; WORD retcode; WORD handle[16], p1, p2, p3, p4; // Rockey Variable DWORD lp1, lp2; // Rockey Variable BYTE buffer[1024]; // Rockey Variable p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find all Rockey for (i=0;i<16;i++) { if (0 == i) { retcode = Rockey(RY_FIND, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; } else { // Notice : lp1 = Last found hardID retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; } if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Found Rockey: %08X ", lp1); retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } rynum = i; // Do our work for (i=0;i<rynum;i++) { // Read Rockey user memory p1 = 0; // Pos p2 = 12; // Length buffer[12] = 0; retcode = Rockey(RY_READ, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("%s\n", buffer); // Output lp1=0; retcode = Rockey(RY_READ_USERID, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Read User ID: %08X\n", lp1); p1=0; retcode = Rockey(RY_CHECK_MOUDLE, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4,buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Check Moudle 0: "); if (p2) printf("Allow "); elseprintf("No Allow "); if (p3) printf("Allow Decrease\n"); elseprintf("Not Allow Decrease\n"); } // Close all opened Rockey for (i=0;i<rynum;i++) { retcode = Rockey(RY_CLOSE, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } } A maximum of 16 dongles may be attached to the same computer at the same time. The program can access any dongle you specify. In the above program we defined a handle array to save the opened Rockey4ND handle to prepare for the next operation on the specified dongle. When we find the dongle we open it and we close all opened Rockey4ND handles before exiting the program. Developers are better off operating in this manner, but for a large program it is OK to open/close the dongle just once at the beginning/end of the program. Frequent open and close operations will reduce performance. We open the dongle in share mode so that another programs may also simultaneously operate with the dongle. Note: We called function RY_OPEN and RY_CLOSE in the above program. We must open Rockey4ND before all operations with the exceptions of RY_FIND and RY_FIND_NEXT. This is similar to the operation on the disk files. You should close the dongle immediately after finishing dongle related operations. 2. Advanced Application Examples This section is dedicated to providing additional illustrative examples of methods you may employ to protect your software with Rockey4ND. These examples are intentionally simplified and not intended to be a complete solutions for software protection. The method appropriate for your application will depend on constraints set by your licensing agreement and other factors. (If you are familiar with the API call already, you may skip to Chapter 7 Writing Hardware Algorithm.) 2.1)User Data Zone advanced application. In Step 14 we will write “Hello FEITIAN!” to User Data Zone (UDZ). In general we would write “Hello FEITIAN!” to the UDZ as one character string, but security may be enhanced by writing it in two parts and then later combining the character strings. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; BYTE buf[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0; p4 = 0; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { p1 = 0; p2 = 10; strcpy((char*)buffer, "Hello "); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write: Hello \n"); p1 = 12; p2 = 12; strcpy((char*)buffer, "FEITIAN!"); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write: FEITIAN!\n"); p1 = 0; p2 = 10; memset(buffer, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buffer); p1 = 12; p2 = 12; memset(buf, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buf); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buf); printf("\n"); printf("%s\n", strcat(buffer,buf)); retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } getch(); } } Step 15: You may write a serial number in the User Data Zone (UDZ) and then verify it during run time as a means of protecting and controlling a program module. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { p1 = 0; p2 = 12; strcpy((char*)buffer, "a1b2c3d4e5f6"); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write:a1b2c3d4e5f6\n"); p1 = 0; p2 = 2; memset(buffer, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buffer); if (!strcmp(buffer,"a1")) printf("Run Module 1\n"); else break; p1 = 2; p2 = 2; memset(buffer, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buffer); if (!strcmp(buffer,"b2")) printf("Run Module 2\n"); else break; retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); getch(); } } Step 16: Write a number to the UDZ and decrease it during run time as a means of controlling a software module. We recommend you use the encryption idea in Step 12 combined with Step 16. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; int i, j,num; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0; p4 = 0; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { p1 = 0; p2 = 1; strcpy((char*)buffer, "3"); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode){ ShowERR(retcode); return; } printf("Write: 3\n"); p1 = 0; p2 = 1; memset(buffer, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buffer); num=atoi(buffer); if(num) { printf("HelloFEITIAN!\n"); num--; } else { return; } p1 = 0; p2 = 1; sprintf(buffer, "%ld", num); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write: %ld\n",num); retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); } } } 2.2) Seed code advanced applications. Step 17: You may use different seed codes for different software modules or in different places in the application. Then verify the seed codes in the applications. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0; p4 = 0; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { lp2 = 0x12345678; retcode = Rockey(RY_SEED, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); if(p1==0xD03A && p2==0x94D6 && p3==0x96A9 &&p4==0x7F54) printf("Hello Fei!\n"); else break; lp2 = 0x87654321; retcode = Rockey(RY_SEED, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); if(p1==0xB584 && p2==0xD64F && p3==0xC885 && p4==0x5BA0) printf("Hello Tian!\n"); else break; lp2 = 0x18273645; retcode = Rockey(RY_SEED, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); if(p1==0x2F6D && p2==0x27F8 && p3==0xB3EE && p4==0xBE5A) printf("Hello OK!\n"); else break; retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); getch(); } } In Step 18 we use four outputs of the seed code function to encrypt and decrypt a character string. Be sure you only include the “decrypt” portion of the code in the application version that is sent to end users. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { char str[20] = "Hello FEITIAN!"; DWORD mykey = 12345678; int n, slen; WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; int i,j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { // Encrypt my data slen = strlen(str); lp2 = mykey; retcode = Rockey(RY_SEED, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } for (n=0;n<slen;n++) { str[n] = str[n] + (char)p1 + (char)p2 + (char)p3 + (char)p4; } printf("Encrypted data is %s\n", str); // Decrypt my data lp2 = mykey; retcode = Rockey(RY_SEED, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } for (n=0;n<slen;n++) { str[n] = str[n] - (char)p1 - (char)p2 - (char)p3 - (char)p4; } printf("Decrypted data is %s\n", str); retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); getch(); } } 2.3) User ID advanced applications Step 19: Some developers will write the current date to the UID when initializing the dongles. During runtime the software may compare the current system time with the date stored in the UID. The program would take appropriate actions or continue based on the results of the comparison. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; BYTE buf[1024]; int i, j; SYSTEMTIME st; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { lp1 = 0x20021101; retcode = Rockey(RY_WRITE_USERID, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4,buffer); if (retcode) { ShowERR(retcode); return; } printf("Write User ID: %08X\n", lp1); lp1 = 0; retcode = Rockey(RY_READ_USERID, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4,buffer); if (retcode) { ShowERR(retcode); return; } printf("Read User ID: %08X\n", lp1); sprintf(buffer,"%08X",lp1); GetLocalTime(&st); printf("Date:%04d%02d%02d\n",st.wYear,st.wMonth,st.wDay); sprintf(buf,"%04d%02d%02d",st.wYear,st.wMonth,st.wDay); if(strcmp(buf,buffer)>=0) { printf("ok!\n"); } else break; retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); getch(); } } 2.4) Module advanced applications. Step 20: Module encryption allows you to selectively control portions of your application with the Rockey4ND modules. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; DWORD lp1, lp2; BYTE buffer[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { p1 = 0; p2 = 0x2121; p3 = 0; retcode = Rockey(RY_SET_MOUDLE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Set Moudle 0: Pass = %04X Decrease no allow\n", p2); p1 = 0; retcode = Rockey(RY_CHECK_MOUDLE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Check Moudle 0: "); if (p2) printf("Run Modul 1!\n"); else break; printf("\n"); p1 = 8; p2 = 0xFFFF; p3 = 0; retcode = Rockey(RY_SET_MOUDLE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Set Moudle 8: Pass = %04X Decrease no allow\n", p2); p1 = 8; retcode = Rockey(RY_CHECK_MOUDLE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Check Moudle 8: "); if (p2) printf("Run Modul 2!"); else break; retcode = Rockey(RY_CLOSE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); } } } Step 21: This program discussed how to perform multi-module encryption and check the status of the modules. Many applications are segmented into program modules that users may choose or purchase separately. For example, a user may purchase three of four available application modules and the licensing policy would allow the user to execute only those modules that were purchased. Rockey4ND modules may be used to enforce this licensing scheme. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void main() { int i, j, rynum; WORD retcode; DWORD HID[16]; WORD handle[16], p1, p2, p3, p4, retcode; p1 = 0xc44c; // Rockey Demo Password 1 p2 = 0xc8f8; // Rockey Demo Password 2 p3 = 0; // Program needn't Password 3, Set to 0 p4 = 0; // Program needn't Password 4, Set to 0 // Try to find all Rockey for (i=0;i<16;i++) { if (0 == i) { retcode = Rockey(RY_FIND, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; } else { // Notice : lp1 = Last found hardID retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; } if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } printf("Found Rockey: %08X\n", lp1); HID[i] = lp1; // Save HardID retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } } printf("\n"); rynum = i; // Do our work for (i=0;i<rynum;i++) { printf("Rockey %08X module status: ", HID[i]); for (j=0;j<16;j++) { p1 = j; // Module No retcode = Rockey(RY_CHECK_MOUDLE, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) // Error { printf("Error Code: %d\n", retcode); return; } if (p2) printf("O"); else printf("X"); } printf("\n"); } // Close all opened Rockey for (i=0;i<rynum;i++) { retcode = Rockey(RY_CLOSE, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { printf("Error Code: %d\n", retcode); return; } } } The above program searches all dongles with the same passwords attached to the computer and displays the status of every module in every listed dongle. “O” means that the module may be used and is not zero; “X” means that the module cannot be used. In a protection scheme that relies on Rockey4ND modules this program would help the developer identify modules that are usable from ones that should be terminated. 2.5) The same code dongle advanced applications. If you have several software products but only a single purchase code – meaning that the passwords are all the same – you may use the solution indicated below to differentiate the dongles. In Step 22 the UDZ is used to distinguish the dongles with the same passwords. For example, the dongles with UDZ content of “Ver 10”correspond to software A. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; WORD handleEnd; DWORD lp1, lp2; BYTE buffer[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; { retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { /*p1 = 0; p2 = 5; strcpy((char*)buffer, "Ver10"); retcode = Rockey(RY_WRITE, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write:%s\n",buffer); */ p1 = 0; p2 = 5; memset(buffer, 0, 64); retcode = Rockey(RY_READ, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n", buffer); if (!strcmp(buffer,"Ver10") { handleEnd=handle[j]; break; } } { //=========A========== retcode = Rockey(RY_RANDOM, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Random: %04X\n", p1); lp2 = 0x12345678; retcode = Rockey(RY_SEED, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); retcode = Rockey(RY_CLOSE, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); } } } In Step 23 the UID is used to distinguish the dongles with the same passwords. For example, dongles with UID of “11111111” (hexadecimal) correspond to software A. #include <stdio.h> #include <string.h> #include "rockey.h" // Include Rockey Header File typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned char BYTE; void ShowERR(WORD retcode) { if (retcode == 0) return; printf("Error Code: %d\n", retcode); } void main() { WORD handle[16], p1, p2, p3, p4, retcode; WORD handleEnd; DWORD lp1, lp2; BYTE buffer[1024]; int i, j; p1 = 0xc44c; p2 = 0xc8f8; p3 = 0x0799; p4 = 0xc43b; { retcode = Rockey(RY_FIND, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Find Rock: %08X\n", lp1); retcode = Rockey(RY_OPEN, &handle[0], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i = 1; while (retcode == 0) { retcode = Rockey(RY_FIND_NEXT, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode == ERR_NOMORE) break; if (retcode) { ShowERR(retcode); return; } retcode = Rockey(RY_OPEN, &handle[i], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } i++; printf("Find Rock: %08X\n", lp1); } printf("\n"); for (j=0;j<i;j++) { /*lp1= 0x11111111; retcode = Rockey(RY_WRITE_USERID, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write User ID: %08X\n", lp1); */ lp1 = 0; retcode = Rockey(RY_READ_USERID, &handle[j], &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } if(lp1==0x11111111) { handleEnd=handle[j]; break; } } { //=======A============= p1 = 0; p2 = 12; strcpy((char*)buffer, "Hello FEITIAN!"); retcode = Rockey(RY_WRITE, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Write: %s\n",buffer); p1 = 0; p2 = 12; buffer[512]=0; retcode = Rockey(RY_READ, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Read: %s\n",buffer); retcode = Rockey(RY_RANDOM, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Random: %04X\n", p1); lp2 = 0x12345678; retcode = Rockey(RY_SEED, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("Seed: %04X %04X %04X %04X\n", p1, p2, p3, p4); retcode = Rockey(RY_CLOSE, &handleEnd, &lp1, &lp2, &p1, &p2, &p3, &p4, buffer); if (retcode) { ShowERR(retcode); return; } printf("\n"); } } }
Copyright (C) 2007-2009 Feitian Technologies Co.,Ltd. All rights reserved. Last Updated: Agu 5, 2009