/* Define API */
#ifndef _PKCSINT_H_
#define _PKCSINT_H_ 1

#ifdef __cplusplus
extern "C" {
#endif

//----------------------------------------
// globals
//----------------------------------------
#ifdef DEBUG_MSGS

#define DEBUG_MSG(STR)                printf(STR);
#define DEBUG_INFO(STR, DATA)         printf(STR, DATA);
#define DEBUG_INFO2(STR, DATA, DATA2) printf(STR, DATA, DATA2);
#define FORMAT_ADD(STR, DATA)         printf(STR, DATA);

#else

#define DEBUG_MSG(STR)                
#define DEBUG_INFO(STR, DATA)                              
#define DEBUG_INFO2(STR, DATA, DATA2)                            
#define FORMAT_ADD(STR,DATA)

#endif

#define DEBUG_MAX               200
#define MESSAGE_LENGTH          256
#define NUMBER_OF_OBJECTS       10

char                                    gDebugData[DEBUG_MAX + 1];
  
#define INVALID_SLOTID  ((unsigned long) -1)
#define INVALID_SESSION ((unsigned long) -1)

//
// Types specific to the Virtual SC implimentation
//

typedef FILE * CRYPTO_TOKEN_HANDLE;  


#define TOKEN_NAME              "C:\\WINNT\\PKCS11.INI\0"
#define DEFAULT_TOKEN_NAME      "C:\\TOKEN.FIL"
#define TOKEN_FILE_NAME_LEN		64
#define DEFAULT_SO_PIN			"SOPIN"
#define PIN_HASH_LEN			16
#define CRYPTOKI_MAX_SESSIONS		20
#define CRYPTOKI_MAX_SLOTS		8
#define CRYPTOKI_MAJOR			2
#define CRYPTOKI_MINOR			0
#define LIBRARY_MAJOR			1
#define LIBRARY_MINOR			0
#define PUBLIC_OBJECT_SIZE      8192
#define PRIVATE_OBJECT_SIZE     8192
#define PUBLIC_OBJECT			0
#define PRIVATE_OBJECT			1000
#define TOKEN_LABEL 			"Jonah Virtual Smart Card        "
#define MANUFACTURER_ID 		"IBM Corporation                 "
#define TOKEN_MANUFACTURER		"Jonah VSC 1.0   "
#define TOKEN_FLAGS				0
#define TOKEN_MAX_SESSIONS		8
#define TOKEN_MAX_RW_SESSIONS	1
#define TOKEN_MAX_PIN_LEN		8
#define TOKEN_MIN_PIN_LEN		3
#define TOKEN_HARDWARE_MAJOR	1
#define TOKEN_HARDWARE_MINOR	0
#define TOKEN_FIRMWARE_MAJOR	1
#define TOKEN_FIRMWARE_MINOR	0
#define TOKEN_UTC				"                "
#define TOKEN_SN_LEN			16
#define TOKEN_LOGON_TRIES		10

#define SLOT_HARDWARE_MAJOR		1
#define SLOT_HARDWARE_MINOR		0
#define SLOT_FIRMWARE_MAJOR		1
#define SLOT_FIRMWARE_MINOR		0

#define CRYPT_KEY				{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6}
#define DECRYPT_KEY				{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6}
#define SN_SEED					55

// 
// Ini file structures
//
typedef struct CRYPTOKI_INI {
	CK_CHAR		token_file[TOKEN_FILE_NAME_LEN];
} CRYPTOKI_INI;

typedef CRYPTOKI_INI	CK_PTR	CRYPTOKI_INI_PTR;

//
// PKCS Structures
//

struct object_template {
    CK_ULONG                    attribute;
    CK_ULONG                    value_size;
    CK_BYTE_PTR                 pvalue;
    struct object_template      *pnext;
};

typedef struct object_template          OBJECT_TEMPLATE;

typedef struct object_template CK_PTR   OBJECT_TEMPLATE_PTR;

struct token_object {
    OBJECT_TEMPLATE_PTR pobject;        // first object template
    CK_ULONG            numtemplates;
	CK_OBJECT_HANDLE	ohandle;
    struct token_object *pnext;
};

typedef struct token_object             TOKEN_OBJECT;

typedef struct token_object CK_PTR      TOKEN_OBJECT_PTR;

typedef struct CRYPTO_SESSION_INFO {
    CK_SLOT_ID          session_slot;
    CK_STATE            session_state;
    CK_FLAGS            session_flags;
    CK_ULONG            ulDeviceError;
    CK_SESSION_HANDLE   session_handle;
    CK_NOTIFY           session_notification;
    CK_VOID_PTR         session_pApplication;
    CRYPTO_TOKEN_HANDLE token_handle;
    CK_ULONG            maxpinlen;
    CK_ULONG            minpinlen;
	CK_SESSION_HANDLE	search_session;
	CK_ATTRIBUTE_PTR	psearch_object;
	CK_ULONG			search_count;
	CK_ULONG			current_object;
	// Stuff that identifies process/thread as unique
} CRYPTO_SESSION_INFO;

typedef CRYPTO_SESSION_INFO     CK_PTR  CRYPTO_SESSION_INFO_PTR;

typedef struct CRYPTO_SLOT_INFO {
	TOKEN_OBJECT_PTR    ppublic_object_list;
	TOKEN_OBJECT_PTR    pprivate_object_list;
	CK_SLOT_INFO_PTR    slot;
	CK_BBOOL			slot_event;
} CRYPTO_SLOT_INFO;

typedef CRYPTO_SLOT_INFO	CK_PTR	CRYPTO_SLOT_INFO_PTR;

typedef struct CRYPTO_TOKEN_SECURE_INFO {
    CK_CHAR             sopin[PIN_HASH_LEN];
    CK_ULONG            sopinlen;
	CK_ULONG			badsotries;
    CK_CHAR             userpin[PIN_HASH_LEN];
    CK_ULONG            userpinlen;
	CK_ULONG			badusertries;
} CRYPTO_TOKEN_SECURE_INFO;

typedef CRYPTO_TOKEN_SECURE_INFO  CK_PTR  CRYPTO_TOKEN_SECURE_INFO_PTR;

typedef struct CRYPTO_PUBLIC_OBJECTS {
    CK_ULONG            headp_offset; 
    CK_ULONG            freep_offset;
    CK_ULONG            numobjects;
    CK_BYTE             publicobject[PUBLIC_OBJECT_SIZE];
} CRYPTO_PUBLIC_OBJECTS;

typedef struct CRYPTO_PUBLIC_OBJECTS CK_PTR CRYPTO_PUBLIC_OBJECTS_PTR;

typedef struct CRYPTO_PRIVATE_OBJECTS {  
    CK_ULONG            headp_offset;
    CK_ULONG            freep_offset;
    CK_ULONG            numobjects;
    CK_BYTE             privateobject[PRIVATE_OBJECT_SIZE];
} CRYPTO_PRIVATE_OBJECTS;

typedef struct CRYPTO_PRIVATE_OBJECTS CK_PTR CRYPTO_PRIVATE_OBJECTS_PTR;

typedef struct CRYPTO_TOKEN {                      
    CK_TOKEN_INFO               token_info;
    CRYPTO_TOKEN_SECURE_INFO    token_secure;
    CRYPTO_PUBLIC_OBJECTS       token_public;
    CRYPTO_PRIVATE_OBJECTS      token_private;
} CRYPTO_TOKEN;

typedef struct CRYPTO_TOKEN CK_PTR CRYPTO_TOKEN_PTR;

//
// Cryptoki functions
//

CK_RV PKCS_init_cryptoki(CK_INFO_PTR *);

CK_RV PKCS_init_slot(CK_SLOT_INFO_PTR *);

CK_RV PKCS_finalize_slot(CK_SLOT_INFO_PTR *);

// 
// Internal Session Functions
//

CRYPTO_TOKEN_HANDLE PKCS_open_card_session(CK_CHAR_PTR, CRYPTO_SESSION_INFO_PTR);  

CK_RV PKCS_close_card_session(CRYPTO_TOKEN_HANDLE); 

CK_SESSION_HANDLE	PKCS_Get_Available_Session(CRYPTO_SESSION_INFO_PTR *,  CK_ULONG, CK_SLOT_ID, CK_ULONG);

CK_SESSION_HANDLE	PKCS_Get_Exclusive_Session(CRYPTO_SESSION_INFO_PTR *, CK_ULONG, CK_SLOT_ID);

//
// Internal Token Functions
//

CK_RV PKCS_get_token_information(CK_CHAR_PTR, CK_TOKEN_INFO_PTR);

CK_RV PKCS_get_pin_information(CK_CHAR_PTR, CRYPTO_TOKEN_SECURE_INFO_PTR);

CK_RV PKCS_get_public_objects(CK_CHAR_PTR, TOKEN_OBJECT_PTR *);

CK_RV PKCS_get_private_objects(CK_CHAR_PTR, TOKEN_OBJECT_PTR *);

CK_RV PKCS_write_user_pin(CK_CHAR_PTR, CK_CHAR_PTR, CK_ULONG); 

CK_RV PKCS_write_so_pin(CK_CHAR_PTR, CK_CHAR_PTR, CK_ULONG);

CRYPTO_TOKEN_HANDLE PKCS_token_init(CK_CHAR_PTR, CK_CHAR_PTR, CK_ULONG);

CK_RV PKCS_add_object(CK_CHAR_PTR, TOKEN_OBJECT_PTR *, TOKEN_OBJECT_PTR *, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR); 

CK_RV PKCS_find_object(TOKEN_OBJECT_PTR, TOKEN_OBJECT_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG_PTR, CK_OBJECT_HANDLE_PTR, CK_ULONG, CK_ULONG_PTR);

CK_RV PKCS_get_object_size(TOKEN_OBJECT_PTR, TOKEN_OBJECT_PTR, CK_OBJECT_HANDLE, CK_ULONG_PTR);

CK_RV PKCS_get_object_data(TOKEN_OBJECT_PTR, TOKEN_OBJECT_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE);

CK_RV PKCS_destroy_object(TOKEN_OBJECT_PTR *, TOKEN_OBJECT_PTR *, CK_OBJECT_HANDLE);

CK_RV PKCS_invalid_user_attempts(CK_CHAR_PTR);

CK_RV PKCS_reset_user_attempts(CK_CHAR_PTR);

CK_RV PKCS_invalid_so_attempts(CK_CHAR_PTR);

CK_RV PKCS_reset_so_attempts(CK_CHAR_PTR);

CK_RV PKCS_free_objects(TOKEN_OBJECT_PTR);

void PKCS_generate_serial_number(CK_CHAR_PTR, CK_ULONG);

void PKCS_crypt_data(CK_CHAR_PTR, CK_ULONG);

void PKCS_decrypt_data(CK_CHAR_PTR, CK_ULONG);

unsigned long JONAH_get_token_name(char *);

unsigned long JONAH_get_initial_SO_pin(char *);  

#ifdef __cplusplus
}
#endif

#endif
