Source: pkcs11.js

/**
 * ------------------------------------------------------------------------------
 *
 *     Copyright (c) 2017  GEMALTO DEVELOPPEMENT - R&D
 *
 * ------------------------------------------------------------------------------
 * GEMALTO MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. GEMALTO SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). GEMALTO
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 *
 * ------------------------------------------------------------------------------
 */


/* ------------------------------------------------------------------------------ */
/* JSHint configuration */
/* ------------------------------------------------------------------------------ */
/*jslint bitwise: true */
/*global SConnect: true */
/*global LoggingService : true */
/*global window : true */


// ------------------ PKCS11 add-on Info -----------


/**
 * @public
 * @description PKCS11 add-on Info. This object is used internally to identify the add-on into the SConnect framework.
 * @constructor
 */
SConnect.PKCS11Info = function () {
    'use strict';

    /**
     * PKCS11 add-on version
     * @type String
     */
    this.packageVersion = "1.9.10.8";

    /**
     * PKCS11 add-on URL
     * @type Object
     */
    this.packageURL = {
        win: "pkcs11/pkcs11-win-v" + this.packageVersion + ".pkg",
        win64: "pkcs11/pkcs11-win64-v" + this.packageVersion + ".pkg",
        lx: "pkcs11/pkcs11-lx-v" + this.packageVersion + ".pkg",
        lx64: "pkcs11/pkcs11-lx64-v" + this.packageVersion + ".pkg",
        osx: "pkcs11/pkcs11-osx-v" + this.packageVersion + ".pkg"
    };

    /**
     * PKCS11 add-on UUID
     * @type String
     */
    this.packageUUID = "e9033d79-1473-42e8-9691-179cb907e279";

    /**
     * PKCS11 add-on display name
     * @type String
     */
    this.packageName = "PKCS11 add-on";
};



// ------------------ PKCS11 Library -----------



/**
 * @public
 * @description PKCS11 add-on object. The constructor is used internaly. The web application must invoke the 'Create' function of this API to create the instance.
 * @constructor
 */
SConnect.PKCS11 = function () {

    'use strict';

    /**
     * @private
     * @description Instance of SConnect.PKCS11Info describing this instance of SConnect.PKCS11
     */
    this.addonInfo = null;

    /**
     * @private
     * @description Unique identifier for this instance of SConnect.PKCS11 attributed after SConnect 'create' invokation
     */
    this.addonId = null;

    /**
     * @private
     */
    this.isDisposed = true;

};


SConnect.PKCS11.prototype = {


    // ------------------ PKCS11 Private Methods -----------


    /**
     * @private
     * @description Invokes SConnect to process the callback after PKCS11 function comes back from execution
     */
    _triggerCallback: function (callback, success, arg1, arg2, arg3) {

        'use strict';
        SConnect._triggerCallback(callback, success, arg1, arg2, arg3);
    },


    /**
     * @private
     * @description Prepares the command to be processed by the SConnect add-on & triggers the response callback 
     */
    _invoke: function (command, params, callback) {

        'use strict';

        LoggingService.debug(" ");
        LoggingService.debug(" == _invoke (BEGIN)");
        LoggingService.debug(" command (" + command + ")");
        LoggingService.debug(" params (" + JSON.stringify(params) + ")");

        // Set default values if parameters are missing
        if (typeof (params) === 'undefined') {
            params = null;
        }

        if (typeof (callback) === 'undefined') {
            callback = null;
        }

        // Store the current 'this' object to invoke the callbacks later in the good context
        var thisObject = this,
            invokeCallback = {

                success: function (response) {


                    // Extract the status from the response coming from the add-on
                    var status = response.status,
                        data = response.data;

                    LoggingService.debug(" == _invoke.success (BEGIN)");
                    LoggingService.debug(" status (" + status + ")");
                    LoggingService.debug(" data (" + JSON.stringify(data) + ")");
                    LoggingService.debug(" == _invoke.success (END)");
                    LoggingService.debug(" ");

                    // Check if the CKR_OK code is present
                    // The status is returned as number (a CK_RV)
                    if (0x00 === status) {


                        // Send back the successful response through the callback
                        thisObject._triggerCallback(callback, true, status, data);

                    } else {

                        // Report the error  through the callback
                        thisObject._triggerCallback(callback, false, status);
                    }
                },
                error: function (status) {

                    LoggingService.debug(" == _invoke.error (BEGIN)");
                    LoggingService.debug(" status (" + status + ")");
                    LoggingService.debug(" == _invoke.error (END)");
                    LoggingService.debug(" ");

                    // TODO Check this status report
                    thisObject._triggerCallback(callback, false, status);
                }
            };

        SConnect._invokeAddOnInstance(this.addonId, command, JSON.stringify(params), invokeCallback);
        LoggingService.debug(" == _invoke (END)");
        LoggingService.debug(" ");
    },


    /**
     * @private
     * @description Creates the instance of the PKCS11 add-on interfaced with this PKCS11 livrary
     */
    createInstance: function (callback) {

        'use strict';
        SConnect._createAddOnInstance(this.addonInfo.packageUUID, this.addonInfo.packageVersion, this.addonInfo.versionType, callback);
    },


    /**
     * @private
     * @description Disposes the instance of the PKCS11 add-on interfaced with this PKCS11 library
     */
    disposeInstance: function (callback) {

        'use strict';
        SConnect._disposeAddOnInstance(this.addonId, this.addonInfo.packageUUID, this.addonInfo.packageVersion, callback);
    },


    /**
     * @private
     * @description Starts the tracking of the PKCS11 events
     */
    registerTokenStatusChangeListener: function (listener, callback) {

        'use strict';
        SConnect._registerAddOnEvent(this.addonId, "TokenStatusChangeEvent", listener, callback);
    },


    /**
     * @private
     * @description Stops the tracking of the PKCS11 events
     */
    unregisterTokenStatusChangeListener: function (callback) {

        'use strict';
        SConnect._unregisterAddOnEvent(this.addonId, "TokenStatusChangeEvent", callback);
    },


    /**
     * @public
     * @instance
     * @memberOf SConnect.PKCS11
     * @description Disposes the PKCS11 instance. This function must be invoked by the web application when the PKCS11 instance is no more usefull.
     * @example
   
     var finalStopTokenEventHandlerCallback = {

    success: function () {

        console.log('StopTokenEventHandler success');

        // Release the PKCS11 object
        if (theObjectPKCS11) {
            theObjectPKCS11.C_Finalize();
            theObjectPKCS11.dispose();
        }
    },

    error: function (code) {

        console.log('StopTokenEventHandler failed ' + code);
    }
};


function onPageUnload() {

    'use strict';

    // Stop the PKCS11 event handler first to release the PKC11
    SConnect.PKCS11.StopTokenEventHandler(finalStopTokenEventHandlerCallback);
}
     */
    dispose: function () {

        'use strict';
        if (!this.isDisposed) {

            // dispose the addon instance
            this.disposeInstance(null);

            this.addonId = null;
            this.isDisposed = true;
        }
    },




    // ------------------ PKCS11 Public Methods -----------



    /**
     * @public
     * @memberOf SConnect.PKCS11 
     * @function C_Initialize
     * @desc Initializes the PKCS#11 library.
     * @param {Object} callback object called when the operation is finished.
     * <ul>
     *   <li> callback.success(status, data) - function called when the function completed successfully</li>
     *   <li> callback.error(errorcode) - function called when the function failed</li>
     * </ul>
     * @example 
     
var callback = {

        success : function (status, data) {

            alert("The function returned the CK_RV (" + status + )");
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    };
theObjectPKCS11.C_Initialize(callback);
         
     */
    C_Initialize: function (callback) {

        'use strict';

        var params = {},
            thisObject = this,
            invokeCallback = {

                success: function (status, data) {

                    thisObject._triggerCallback(callback, true, status, data);
                },
                error: function (status) {

                    thisObject._triggerCallback(callback, false, status);
                }
            };
        params.addonVersion = this.addonInfo.packageVersion;

        this._invoke("C_Initialize", params, invokeCallback);
    }
};




/**
 * @public
 * @memberOf SConnect.PKCS11 
 * @function C_Finalize
 * @desc Disposes the PKCS#11 library.
 * @param {Object} callback object called when the operation is finished.
 * 
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @example 
 
var callback = {

        success : function (status, data) {

            alert("The function returned the CK_RV (" + status + )");
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    };
theObjectPKCS11.C_Finalize(callback);
    
 */
SConnect.PKCS11.prototype.C_Finalize = function (callback) {

    'use strict';

    var params = null,
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
				window.internal_pkcs11_ir_scom.dispose();
				window.internal_pkcs11_ir_scom = null;
				window.internal_pkcs11_ir_callback = null;
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };

    this._invoke("C_Finalize", params, invokeCallback);
};


/**
 * @public
 * @memberOf SConnect.PKCS11 
 * @function C_GetInfo
 * @desc Returns general information about Cryptoki.
 * @param {Object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @return The success function of the callback returns CK_INFO JSON object:
 <pre>
 &#123;
    "cryptokiVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125,
    "manufacturerID" : TypeString,
    "flags" : TypeNumber,
    "libraryDescription" : TypeString,
    "libraryVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125
 &#125
</pre>
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_INFO information:";
            message + "cryptokiVersion (" + data.cryptokiVersion.major + " - " + data.cryptokiVersion.major + ")";
            message + "manufacturerID (" + data.manufacturerID + ")";
            message + "flags (" + data.flags + ")";
            message + "libraryDescription (" + data.libraryDescription + ")";
            message + "libraryVersion (" + data.libraryVersion.major + " - " + data.libraryVersion.major + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    };
theObjectPKCS11.C_GetInfo(callback);
    
*/
SConnect.PKCS11.prototype.C_GetInfo = function (callback) {

    'use strict';

    var params = null,
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };

    this._invoke("C_GetInfo", params, invokeCallback);
};




/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_GetSlotList
* @desc Returns a list of slots in the system.
* @param {Boolean} tokenPresent indicates whether the list obtained includes only those slots with a token present (true), or all slots (false).
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns a [1..n] JSON array of Numbers for the CK_SLOT_ID available with or without token inserted accordingly the 'tokenPresent' parameter provided.
* For example the PKCS11 add-on sends back the array [1, 2, 3] if the slot with the identifier 1 and the slot with identifier 2 and the slot woth identifier 3 are available.
* @example 

var callback = {

        success : function (status, data) {

            var message = "The available slots are :";
            for (var i = 0, len = data.length; i < len; i++) {
              message += data[i];
              message += " ";
            }
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    tokenPresent = true;
theObjectPKCS11.C_GetSlotList(tokenPresent,callback);
  
*/
SConnect.PKCS11.prototype.C_GetSlotList = function (tokenPresent, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };

    params.tokenPresent = tokenPresent;
    //params['tokenPresent'] = tokenPresent;

    this._invoke("C_GetSlotList", params, invokeCallback);
};







/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_GetSlotInfo
* @desc Obtains information about a particular slot in the system.
* @param {Number} slotId slot identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns CK_SLOT_INFO JSON object:
 <pre>
 &#123;
    "slotDescription" : TypeString,
    "manufacturerID" : TypeString,
    "flags" : TypeNumber,
    "hardwareVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125,
    "firmwareVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125        
 &#125
</pre>
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_SLOT_INFO information:";
            message + "cryptokiVersion (" + data.cryptokiVersion.major + " - " + data.cryptokiVersion.major + ")";
            message + "manufacturerID (" + data.manufacturerID + ")";
            message + "flags (" + data.flags + ")";
            message + "libraryDescription (" + data.libraryDescription + ")";
            message + "libraryVersion (" + data.libraryVersion.major + " - " + data.libraryVersion.major + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    slotId = 1;
theObjectPKCS11.C_GetSlotInfo(slotId, callback);
    
*/
SConnect.PKCS11.prototype.C_GetSlotInfo = function (slotId, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;

    this._invoke("C_GetSlotInfo", params, invokeCallback);
};




/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_GetTokenInfo
* @desc Obtains information about a particular token in the system.
* @param {Number} slotId slot identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns CK_TOKEN_INFO JSON object:
 <pre>
 &#123;
    "label" : TypeString,
    "manufacturerID" : TypeString,
    "model" : TypeString,
    "serialNumber" : TypeString,
    "flags" : TypeNumber,
    "maxSessionCount" : TypeNumber,
    "sessionCount" : TypeNumber,
    "maxRwSessionCount" : TypeNumber,
    "rwSessionCount" : TypeNumber,
    "maxPinLen" : TypeNumber,
    "minPinLen" : TypeNumber,
    "totalPublicMemory" : TypeNumber,
    "freePublicMemory" : TypeNumber,
    "totalPrivateMemory" : TypeNumber,
    "freePrivateMemory" : TypeNumber,
    "hardwareVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125,
    "firmwareVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125,        
    "time" : String
 &#125
</pre>
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_TOKEN_INFO information:";
            message + "label (" + data.label + ")";
            message + "manufacturerID (" + data.manufacturerID + ")";
            message + "model (" + data.model + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    slotId = 1;
theObjectPKCS11.C_GetTokenInfo(slotId, callback);
    
*/

SConnect.PKCS11.prototype.C_GetTokenInfo = function (slotId, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;

    this._invoke("C_GetTokenInfo", params, invokeCallback);
};







/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_GetMechanismList
* @desc Obtains the list of mechanism types supported by a token.
* @param {Number} slotId slot identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns a [1..n] JSON array of Numbers for the CK_MECHANISM_TYPE available accordingly the 'slotId' parameter provided.
* For example the PKCS11 add-on sends back the array [0, 1, 6] if the mechanism types CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS and CKM_SHA1_RSA_PKCS are available.
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_MECHANISM_TYPE: ";
            for (var i = 0, len = data.length; i < len; i++) {
                message += " " + data[i];
            }
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    slotId = 1;
theObjectPKCS11.C_GetMechanismList(slotId, callback);
    
*/

SConnect.PKCS11.prototype.C_GetMechanismList = function (slotId, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    this._invoke("C_GetMechanismList", params, invokeCallback);
};


/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_GetMechanismInfo
* @desc Obtains information about a particular mechanism possibly supported by a token.
* @param {Number} slotId slot identifier.
* @param {Number} mechanismType mechanism type to get information about.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns CK_MECHANISM_INFO JSON object:
 <pre>
 &#123;
    "minKeySize" : TypeNumber,
    "maxKeySize" : TypeNumber,
    "flags" : Number
 &#125
</pre>
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_MECHANISM_INFO information:";
            message + "minKeySize (" + data.minKeySize + ")";
            message + "maxKeySize (" + data.maxKeySize + ")";
            message + "flags (" + data.flags + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    mechanismType = 1, 
    slotId = 1;
    
theObjectPKCS11.C_GetMechanismInfo(slotId, mechanismType, callback);
    
*/

SConnect.PKCS11.prototype.C_GetMechanismInfo = function (slotId, mechanismType, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    params.mechanismType = mechanismType;

    this._invoke("C_GetMechanismInfo", params, invokeCallback);
};




/**
* @private
* @memberOf SConnect.PKCS11 
* @function C_InitToken
* @desc Initializes the token.
* @param {Number} slotId of the token's slot.
* @param {String} pin is the security officer’s PIN formated as plain text.
* @param {String} Label is the label to apply on the token formated as plain text.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @example
var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    slotId = 1,
    pin = "87654321",
    label = "The new name for my token";
theObjectPKCS11.C_InitPIN(slotId, pin, label, callback);
*/

SConnect.PKCS11.prototype.C_InitToken = function (slotId, pin, label, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    params.pin = pin;
    params.label = label;

    this._invoke("C_InitToken", params, invokeCallback);
};



/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_InitPIN
* @desc Initializes the normal user’s PIN.
* @param {Number} sessionHandle is the handle of the session.
* @param {String} pin is the normal user’s PIN formated as plain text.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    pin = "1234";
theObjectPKCS11.C_InitPIN(sessionHandle, pin, callback);
    
*/

SConnect.PKCS11.prototype.C_InitPIN = function (sessionHandle, pin, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.pin = pin;

    this._invoke("C_InitPIN", params, invokeCallback);
};





/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_SetPIN
* @desc Modifies the PIN of the user that is currently logged in, or the CKU_USER PIN if the session is not logged in.
* @param {Number} sessionHandle is the handle of the session.
* @param {String} oldPin is the old user’s PIN formated as plain text.
* @param {String} newPin is the new user’s PIN formated as plain text.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    oldPin = "1234",
    newPin = "5678";
theObjectPKCS11.C_SetPIN(sessionHandle, oldPin, newPin, callback);
    
*/

SConnect.PKCS11.prototype.C_SetPIN = function (sessionHandle, oldPin, newPin, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.oldPin = oldPin;
    params.pin = newPin;

    this._invoke("C_SetPIN", params, invokeCallback);
};





/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_OpenSession
* @desc Opens a session between an application and a token in a particular slot.
* @param {Number} slotId is the slot identifier.
* @param {Number} flags indicates the type of session (read, read/write, serial).
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    // Prepare to open a session on the slotId 1
    slotId = 1,
    // Prepare the flags to open a RW session (CKF_SERIAL_SESSION | CKF_RW_SESSION = 6)
    flags = 6;
theObjectPKCS11.C_OpenSession(slotId, flags, callback);  
*/
SConnect.PKCS11.prototype.C_OpenSession = function (slotId, flags, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    params.flags = flags;

    this._invoke("C_OpenSession", params, invokeCallback);
};




/**
* @public
* @memberOf SConnect.PKCS11 
* @function C_CloseSession
* @desc Closes a session between an application and a token in a particular slot.
* @param {Number} sessionHandle session identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 2;
theObjectPKCS11.C_CloseSession(sessionHandle, callback);
    
*/

SConnect.PKCS11.prototype.C_CloseSession = function (sessionHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;

    this._invoke("C_CloseSession", params, invokeCallback);
};




/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_CloseAllSessions
* @desc Closes all sessions an application has with a token.
* @param {Number} slotId is the slot identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    slotId = 0; // Slot identifer as returned by the C_GetSlotList function
theObjectPKCS11.C_CloseAllSession(slotId, callback);
    
*/

SConnect.PKCS11.prototype.C_CloseAllSessions = function (slotId, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;

    this._invoke("C_CloseAllSessions", params, invokeCallback);
};




/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_GetSessionInfo
* @desc Obtains information about a session.
* @param {Number} sessionHandle session identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns CK_SESSION_INFO JSON object:
 &#123;
    "slotId" : Number,
    "state" : Number,
    "flags" : Number,
    "deviceError" : Number
 &#125
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following CK_SESSION_INFO object: ";
            message += "slot id (" + data.slotId + ")";
            message += "state (" + data.state + ")";
            message += "flags (" + data.flags + ")";
            message += "deviceError (" + data.deviceError + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 2;
theObjectPKCS11.C_GetSessionInfo(sessionHandle, callback);
    
*/

SConnect.PKCS11.prototype.C_GetSessionInfo = function (sessionHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;

    this._invoke("C_GetSessionInfo", params, invokeCallback);
};





/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Login
* @desc Logs a user into a token.
* @param {Number} sessionHandle session identifier.
* @param {Number} userType is the user type (standard user, security officer).
* @param {String} pin is the user's PIN as plain text.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    userType = 1,
    pin = "1234";
theObjectPKCS11.C_Login(sessionHandle, userType, pin, callback);
    
*/

SConnect.PKCS11.prototype.C_Login = function (sessionHandle, userType, pin, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.userType = userType;
    params.pin = pin;

    this._invoke("C_Login", params, invokeCallback);
};






/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Logout
* @desc Logs a user out from a token.
* @param {Number} sessionHandle session identifier.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 2;
theObjectPKCS11.C_Logout(sessionHandle, callback);
    
*/
SConnect.PKCS11.prototype.C_Logout = function (sessionHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;

    this._invoke("C_Logout", params, invokeCallback);
};






/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_CreateObject
* @desc Creates a new object from a given template.
* @param {Number} sessionHandle session identifier.
* @param {Object} attributes JSON object containing all the attributes of the object to create.
The attribute name is described into the PKCS11 specification. All available attributes are described with the prefixe "CKA_". 
The attribute value can be a boolean (with value true or false), a number, a string or a byte array.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @return The success function of the callback returns an object data with the property key 'objectHandle' containing the value of the created object.
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the object handle (" + data.objectHandle + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    attributesData;

// The attribute name is any CKA_ characteristic as defined in the PKCS11 specification
// The attribute value can be a boolean (with value true or false), a number, a string or a byte array.
// Here is the create a data object using the attributes CKA_CLASS, CKA_TOKEN, CKA_APPLICATION and CKA_VALUE.
attributesData.CKA_CLASS = 0;
attributesData.CKA_TOKEN = true;
attributesData.CKA_APPLICATION = [84, 101, 115, 116, 32, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110];
attributesData.CKA_VALUE = [84, 104, 105, 115, 32, 105, 115, 32, 116, 104, 101, 32, 118, 97, 108, 117, 101, 32, 111, 102, 32, 116, 104, 101, 32, 100, 97, 116, 97, 32, 111, 98, 106, 101, 99, 116];
attributesData.CKA_LABEL = [84, 104, 105, 115, 32, 105, 115, 32, 116, 104, 101, 32, 108, 97, 98, 101, 108, 32, 111, 102, 32, 116, 104, 101, 32, 100, 97, 116, 97, 32, 111, 98, 106, 101, 99, 116];
theObjectPKCS11.C_CreateObject(sessionHandle, attributesData, callback);    
*/
SConnect.PKCS11.prototype.C_CreateObject = function (sessionHandle, attributes, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.attributes = attributes;

    this._invoke("C_CreateObject", params, invokeCallback);
};




/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_DestroyObject
* @desc Destroys an object.
* @param {Number} sessionHandle session identifier.
* @param {Number} objectHandle handle of the object to delete.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    objectHandle = 12;
    
theObjectPKCS11.C_DestroyObject(sessionHandle, objectHandle, callback);
    
*/
SConnect.PKCS11.prototype.C_DestroyObject = function (sessionHandle, objectHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = objectHandle;

    this._invoke("C_DestroyObject", params, invokeCallback);
};




/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_GetAttributeValue
* @desc Obtains the value of one or more attributes of an object.
* @param {Number} sessionHandle session identifier.
* @param {Number} objectHandle handle of the object to get attribute from.
* @param {Object} attributes CK_ATTRIBUTE_TYPE array containing all the attributes to get.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the attributes :";
            for(var key in data) {
                message += "attribute (" + key + ") - value (" + data[key] + ")";
            }
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    objectHandle = 12,
    // Set a byte array to get the CKA_CLASS (0x00000000), CKA_TOKEN (0x00000001) and CKA_VALUE (0x00000011) attribute of the object
    attributes = [0, 1, 11];
    
theObjectPKCS11.C_GetAttributeValue(sessionHandle, objectHandle, attributes, callback);
    
*/
SConnect.PKCS11.prototype.C_GetAttributeValue = function (sessionHandle, objectHandle, attributes, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = objectHandle;
    params.attributes = attributes;

    this._invoke("C_GetAttributeValue", params, invokeCallback);
};





/**
* @public
* @instance
* @instance
* @memberOf SConnect.PKCS11 
* @function C_SetAttributeValue
* @desc Modifies the value of one or more attributes of an object.
* @param {Number} sessionHandle session identifier.
* @param {Number} objectHandle handle of the object to get attribute from.
* @param {Object} attributes JSON object containing all the attributes to set. The attribute can be a boolean (with value true or false), a number, a string or a byte array.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the attributes :";
            for(var i in data) {
                message += "attribute (" + i + ") - value (" + data[i] + ")";
            }
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    objectHandle = 12,
    attributes;
    
// The attribute can be a boolean (with value true or false), a number, a string or a byte array.
attributes.CKA_CLASS = 0;
attributes.CKA_TOKEN = true;
attributes.CKA_LABEL = [12,13,14,15,16];

theObjectPKCS11.C_SetAttributeValue(sessionHandle, objectHandle, attributes, callback);
    
*/
SConnect.PKCS11.prototype.C_SetAttributeValue = function (sessionHandle, objectHandle, attributes, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = objectHandle;
    params.attributes = attributes;

    this._invoke("C_SetAttributeValue", params, invokeCallback);
};




/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_FindObjects
* @desc Searches for token and session objects that match a template.
* <strong>This function invokes internally the C_FindObjectsInit, C_FindObjects and C_FindObjectsFinal functions and sends back the result.</strong>
* @param {Number} sessionHandle session identifier.
* @param {Object} attributes JSON object containing all the attributes to search for.
The attribute can be a boolean (with value true or false), a number, a string or a byte array.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success function of the callback returns an array of object handles matching the searched attributes.

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the object handles:";
            for(var key in data) {
                message += "object (" + data[key] + ")";
            }
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    attributes;

// Search all the CKO_DATA available in the token
attributes.CKA_CLASS = 0;
    
theObjectPKCS11.C_FindObjects(sessionHandle, attributes, callback);
    
*/
SConnect.PKCS11.prototype.C_FindObjects = function (sessionHandle, attributes, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.attributes = attributes;

    this._invoke("C_FindObjects", params, invokeCallback);
};





/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Decrypt
* @desc Decrypts encrypted data in a single part.
* <strong>This function invokes internally the C_DecryptInit, C_Decrypt and C_DecryptFinal functions and sends back the result.</strong>
* @param {Number} sessionHandle session identifier.
* @param {Number} keyObjectHandle object handle of the key that is used for decryption.
* @param {Number} mechanismType mechanism type to use for decryption.
* @param {Array} data byte array containing the buffer to decrypt.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success function of the callback returns an 'buffer' byte array containing the decrypted data.
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the decrypted data (" + JSON.stringigy(data.buffer) + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    keyObjectHandle = 3333333, // A valid object handle provided by C_FindObjects or C_GenerateKeyPair for example
    mechanismType = 1, // Value of CKM_RSA_PKCS as described in the PKCS11 specification
    encryptedData = [12,13,14,15,16];
    
theObjectPKCS11.C_Decrypt(sessionHandle, keyObjectHandle, mechanismType, encryptedData, callback);
    
*/
SConnect.PKCS11.prototype.C_Decrypt = function (sessionHandle, keyObjectHandle, mechanismType, encryptedData, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = keyObjectHandle;
    params.mechanismType = mechanismType;
    params.data = encryptedData;

    this._invoke("C_Decrypt", params, invokeCallback);
};





/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Encrypt
* @desc Encrypts data in a single part.
* <strong>This function invokes internally the C_EncryptInit, C_Encrypt and C_EncryptFinal functions and sends back the result.</strong>
* @param {Number} sessionHandle session identifier.
* @param {Number} keyObjectHandle object handle of the key that is used for encryption.
* @param {Number} mechanismType mechanism type to use for encryption.
* @param {Array} data byte array containing the buffer to encrypt.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success function of the callback returns a byte array 'buffer' containing the encrypted data.
* @example 

var callback = {
 
        success : function (status, data) {

            var message = "The function returned the following the encrypted data (" + JSON.stringigy(data.buffer) + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    keyObjectHandle = 3333333, // A valid object handle provided by C_FindObjects or C_GenerateKeyPair for example
    mechanismType = 1, // Value of CKM_RSA_PKCS as described in the PKCS11 specification
    data =[12,13,14,15,16];
    
theObjectPKCS11.C_Encrypt(sessionHandle, keyObjectHandle, mechanismType, data, callback);
    
*/
SConnect.PKCS11.prototype.C_Encrypt = function (sessionHandle, keyObjectHandle, mechanismType, data, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = keyObjectHandle;
    params.mechanismType = mechanismType;
    params.data = data;

    this._invoke("C_Encrypt", params, invokeCallback);
};





/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Sign
* @desc Signs data in a single part.
* <strong>This function invokes internally the C_SignInit and C_Sign functions and sends back the result.</strong>
* @param {Number} sessionHandle session identifier.
* @param {Number} keyObjectHandle object handle of the key that is used for signature.
* @param {Number} mechanismType mechanism type to use for signature.
* @param {Array} data byte array containing the buffer to sign.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success callback returns a byte array 'buffer' containing the signature.
* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the signature (" + JSON.stringigy(data.buffer) + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    keyObjectHandle = 3333333, // A valid object handle provided by C_FindObjects or C_GenerateKeyPair for example
    mechanismType = 1, // Use the CKM_RSA_PKCS mechanism type for the signature
    data = [12,13,14,15,16]; // Byte array to sign
    
theObjectPKCS11.C_Sign(sessionHandle, keyObjectHandle, mechanismType, data, callback);
    
*/
SConnect.PKCS11.prototype.C_Sign = function (sessionHandle, keyObjectHandle, mechanismType, data, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {


                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = keyObjectHandle;
    params.mechanismType = mechanismType;
    params.data = data;

    this._invoke("C_Sign", params, invokeCallback);
};





/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_Verify
* @desc Verifies signature in a single part.
* <strong>This function invokes internally the C_VerifyInit, C_Verify and C_VerifyFinal functions and sends back the result.</strong>
* @param {Number} sessionHandle session identifier.
* @param {Number} keyObjectHandle object handle of the key that is used for signature.
* @param {Number} mechanismType mechanism type to use for signature.
* @param {Array} data byte array containing the original buffer used to generate the signature.
* @param {Array} signature byte array containing the signature to verify.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success callback returns a status.

* @example 

var callback = {

        success : function (status, data) {

            var message = "The function returned the following the status (" + status + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    keyObjectHandle = 3333333, // A valid object handle provided by C_FindObjects or C_GenerateKeyPair for example
    mechanismType = 1, // Use the CKM_RSA_PKCS mechanism type for the signature
    data = [12,13,14,15,16], // Original buffer used to generate the signature
    signature = [67, ... , 134]; // signature byte buffer returned by the C_Sign function
    
theObjectPKCS11.C_Verify(sessionHandle, keyObjectHandle, mechanismType, data, signature, callback);
    
*/
SConnect.PKCS11.prototype.C_Verify = function (sessionHandle, keyObjectHandle, mechanismType, data, signature, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = keyObjectHandle;
    params.mechanismType = mechanismType;
    params.data = data;
    params.buffer = signature;

    this._invoke("C_Verify", params, invokeCallback);
};



/**
* @public
* @instance
* @memberOf SConnect.PKCS11 
* @function C_GenerateKeyPair
* @desc Generates a public/private key pair, creating new key objects.
* @param {Number} sessionHandle session identifier.
* @param {Number} mechanismType mechanism type to use for generation.
* @param {Object} attributesPublicKey JSON object containing the attributes of the public key.
* @param {Object} attributesPrivateKey JSON object containing the attributes of the private key. 
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success function of the callback returns the object handles of the new public/private key pair.

* @example 

var callback = {

        success : function (status, data) {

            // Save key handles for other operations
            publicKeyObjectHandle = data.publicKey;
            privateKeyObjectHandle = data.privateKey;
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    mechanismType = 0, // Use the CKM_RSA_PKCS_KEY_PAIR_GEN mechanism type for the key generation
    attributesKeyPublic = {},
    attributesKeyPrivate = {},
    signOnly = false; // Flag to create (or not) sign only keys

// Add the attributes describing the public key (see the PKCS11 specification for attributes list, type & usage)
attributesKeyPublic.CKA_MODULUS_BITS = 2048;
attributesKeyPublic.CKA_TOKEN = true;
attributesKeyPublic.CKA_CLASS = 2; // value CKO_PUBLIC_KEY as defined into the PKCKS11 specification
attributesKeyPublic.CKA_KEY_TYPE = 0; // value CKK_RSA as defined into the PKCKS11 specification
attributesKeyPublic.CKA_PRIVATE = false;
attributesKeyPublic.CKA_ENCRYPT = !signOnly;
attributesKeyPublic.CKA_WRAP = !signOnly;
attributesKeyPublic.CKA_VERIFY_RECOVER = true;
attributesKeyPublic.CKA_VERIFY = true;
attributesKeyPublic.CKA_ID = [116, 101, 115, 116, 48, 49]; // Buffer containing the bytes "test01"
attributesKeyPublic.CKA_PUBLIC_EXPONENT = [1, 0, 1];

// Add the attributes describing the private key (see the PKCS11 specification for attributes list, type & usage)
attributesKeyPrivate.CKA_TOKEN = true;
attributesKeyPrivate.CKA_PRIVATE = true;
attributesKeyPrivate.CKA_EXTRACTABLE = false;
attributesKeyPrivate.CKA_SENSITIVE = true;
attributesKeyPrivate.CKA_DECRYPT = !signOnly;
attributesKeyPrivate.CKA_UNWRAP = !signOnly;
attributesKeyPrivate.CKA_SIGN_RECOVER = true;
attributesKeyPrivate.CKA_SIGN = true;
attributesKeyPrivate.CKA_ID = [116, 101, 115, 116, 48, 49];

theObjectPKCS11.C_GenerateKeyPair(sessionHandle, mechanismType, attributesKeyPublic, attributesKeyPrivate, generateKeyPairCallback);
*/
SConnect.PKCS11.prototype.C_GenerateKeyPair = function (sessionHandle, mechanismType, attributesKeyPublic, attributesKeyPrivate, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.mechanismType = mechanismType;
    params.attributesKeyPublic = attributesKeyPublic;
    params.attributesKeyPrivate = attributesKeyPrivate;

    this._invoke("C_GenerateKeyPair", params, invokeCallback);
};



/**
 * Search for the certificates owned by the device itself
 * @param {number} sessionHandle session identifier
 * @param {number} certificateCategory specifies the category of the searched certificate.
 * <br>As described into the PKCS11 specification for values of the CKA_CERTIFICATE_TYPE attribute, the certificate category can be:
 * <ul>
 * <li>0 = unspecified (default value)</li>
 * <li>2 = authority (CA certificates)</li>
 * </ul>
 * @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>
* @return The success function of the callback returns the object handle(s) of the device certificate(s).
* @example 
var callback = {
        success : function (status, data) {

            // Save key handles for other operations
            publicKeyObjectHandle = data.publicKey;
            privateKeyObjectHandle = data.privateKey;
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222,
    certificateCategory = 2; // Search for CA certificates 
theObjectPKCS11.ETC_GetDeviceCertificate(sessionHandle, certificateCategory, callback);
*/
SConnect.PKCS11.prototype.ETC_GetDeviceCertificates = function (sessionHandle, certificateCategory, callback) {

    'use strict';

    var attributes = {};

    // Search for object with CKA_CLASS attribute set to CKO_CERTIFICATE
    attributes.CKA_CLASS = 1; //CKO_CERTIFICATE

    // Search for object with CKA_CERTIFICATE_TYPE attribute set to CKC_X_509
    attributes.CKA_CERTIFICATE_TYPE = 0; //CKC_X_509;

    // Search for object with CKA_CERTIFICATE_CATEGORY attribute set to the incoming value certificateCategory
    // As described into the PKCS11 specification, the certificate category can be: 0 = unspecified (default value), 1 = token user, 2 = authority, 3 = other entity
    attributes.CKA_CERTIFICATE_CATEGORY = certificateCategory;

    // Search for object with ETCKA_DEVICE_OBJECT attribute set to true
    attributes.ETCKA_DEVICE_OBJECT = true;

    // Search all the available objects in the token
    this.C_FindObjects(sessionHandle, attributes, callback);
};



/**
 * Invokes a device's IOCTL proprietary function.
 * @param {number} slotId   slot identifier
 * @param {number} code     code of the IOCTL function.
 *                          <br>Use the code 15 to invoke the 'get SWYS device charactericts'.
 * @param {object} data     input parameters to provide to the IOCTL function (if required by the IOCTL function).
 *                          <br>With code 15 no data is required.
 * @param {object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @return The success function of the callback returns the result of the IOCTL function invocation.
 * <br>With code 15 the result is an object with all the device characteristics & SWYS features (@see ETC_GetDeviceInformation).
 * @example
 // Retrieve the device's SWYS charactericts
 var slotId = 0,
    ETCK_IODEV_GET_SWYS_INFO = 15;
 theObjectPKCS11.ETC_DeviceIOCTL(slotId, ETCK_IODEV_GET_SWYS_INFO, null, callback);
 */
SConnect.PKCS11.prototype.ETC_DeviceIOCTL = function (slotId, code, data, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    params.code = code;
    params.data = data;

    this._invoke("ETC_DeviceIOCTL", params, invokeCallback);
};




/**
 * @public
 * @instance
 * @memberOf SConnect.PKCS11 
 * @function ETC_SignEx
 * @desc Signs data in a single part using CKM_RSA_PKCS as signature mechanism and CKM_SHA256 as hash mechansim.
 * <strong>This function invokes internally the C_SignInit and ETC_SignEx functions and sends back the result.</strong>
 * @param {number} sessionHandle    session identifier.
 * @param {number} keyObjectHandle    object handle of the key that is used for signature.
 * @param {Array} data   byte array containing the buffer to sign.
 * @param {number} certificateObjectHandle Object handle of the terminal certificate.
 * @param {Array} hidden byte array containing the hidden data
 * @param {Array} hash byte array containing the hash
 * @param {boolean} signaturePKI true for PKI signature, false for OCRA OTP signature
 * @param {Object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @return The success callback returns a byte array 'signatureTerminal' containing the signature provided by the terminal and a byte array 'signatureCard' containing the signature provided by the smart card.
 * @example
var callback = {

        success : function (status, data) {

            var message = "The function returned the following the signature (" + JSON.stringigy(data.buffer) + ")";
            alert(message);
        },
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    },
    sessionHandle = 22222222, // A valid session handle provided by C_OpenSession
    keyObjectHandle = 3333333, // A valid object handle provided by C_FindObjects or C_GenerateKeyPair for example
    data = [41,6D,6F,75,6E,74,3A,0A,31,32,30,30,2C,30,30], // Byte array to sign
    certificateObjectHandle = 77777, // A valid certificate object handle returned by the function 'ETC_GetDeviceCertificate'
    hidden = [32,30,31,35,30,33,33,30,5F,31,36,30,37,32,32], 
    hash = [47,C1,76,D2,22,9F,BB,71,33,6C,D7,23,2A,D4,40,ED,B0,38,A6,6D,8A,05,03,22,67,AC,33,B5,D1,F0,9F,50],
    signaturePKI = true;
    
theObjectPKCS11.ETC_SignEx(sessionHandle, keyObjectHandle, data, certificateObjectHandle, hidden, hash, signaturePKI, callback);                                        
 */
SConnect.PKCS11.prototype.ETC_SignEx = function (sessionHandle, keyObjectHandle, data, certificateObjectHandle, hidden, hash, signaturePKI, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {
            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;
    params.objectHandle = keyObjectHandle;
    params.data = data;
    params.certificateObjectHandle = certificateObjectHandle;
    params.hidden = hidden;
    params.hash = hash;
    params.signaturePKI = signaturePKI;

    this._invoke("ETC_SignEx", params, invokeCallback);
};


/** 
 * @public
 * @memberOf SConnect.PKCS11 
 * @function ETC_GetDeviceInformation
 * @desc Returns SWYYS information about a slot.
 * @param {number} slotId   slot identifier
 * @param {object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @return {object} The success callback function returns an object containing the following properties:
 <pre>
 &#123;
    // SWYS definition version
    "swysVersion" : &#123;
        "major" : TypeNumber,
        "minor" : TypeNumber,
        &#125,
    // ASCII Code FW version
    "fwVersion" : TypeString,
    // Number of rows, BCD coded
    "rows" : TypeNumber,
    // Number of columns, BCD coded
    "columns" : TypeNumber,
    // Supported ISO8859 tables, one Number each, e.g. 0x0F for ISO8859-15
    "isoCharTables" : TypeArray of TypeNumber,
    // Supported languages tables, one String each, ASCII coded according to ISO639-1
    "languages" : TypeArray of TypeString,
    // Serial number, blank padded, ASCII coded
    "serialNumber" : TypeString,
    // Support for Hashing. '01': Only SHA256,'02': Only SHA512,'03': both
    "hashSupport" : TypeNumber,
    // Support for PKI. '01': Only OATH OCRA OTP,'02': Only PKI Signature, '03':both
    "pkiSupport" : TypeNumber,
    // Card serial number, blank padded, ASCII coded
    "cardSerialNumber" : TypeString
 &#125
</pre>
* @example 

var slotId = 2,
    callback = {

        success : function (status, data) {

            var message = "The function returned the following SWYS information:";
            message + "swysVersion (" + data.swysVersion.major + " - " + data.swysVersion.major + ")";
            message + "fwVersion (" + data.fwVersion + ")";
            message + "rows (" + data.rows + ")";
            message + "columns (" + data.columns + ")";
            message + "isoCharTables (" + JSON.stringify(data.isoCharTables) + ")";
            message + "languages (" + JSON.stringify(data.languages) + ")";
            message + "serialNumber (" + data.serialNumber + ")";
            message + "hashSupport (" + data.hashSupport + ")";
            message + "pkiSupport (" + data.pkiSupport + ")";
            message + "cardSerialNumber (" + data.cardSerialNumber + ")";
            alert(message);
        },
        
        error : function (errorCode) {

            alert("The function failed with code (" + errorCode + ")");
        }
    };
    
theObjectPKCS11.ETC_GetDeviceInformation(slotId, callback);
*/
SConnect.PKCS11.prototype.ETC_GetDeviceInformation = function (slotId, callback) {

    'use strict';

    var ETCK_IODEV_GET_SWYS_INFO = 15;

    // Search all the available objects in the token
    this.ETC_DeviceIOCTL(slotId, ETCK_IODEV_GET_SWYS_INFO, null, callback);
};



/**
 * @public
 * @instance
 * @memberOf SConnect.PKCS11 
 * @function ETC_EnableAuthenticationPopup
 * @desc Enables/disables the Gemalto inner popup window displayed during C_Login operation.<br>
 * <strong>This function must be invoked after the session is opened (C_OpenSession).</strong>
 * @param {boolean} flag true to enable and show the Gemalto popup window, false to disable and hide it.
 * @param {object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @example
var callback = {
        success : function (status, data) {
            alert("The function successed");
        },
        error : function (errorCode) {
            alert("The function failed with code (" + errorCode + ")");
        }
    },
    flag = false;
    
theObjectPKCS11.ETC_EnableAuthenticationPopup(flag, callback);                                        
 */
SConnect.PKCS11.prototype.ETC_EnableAuthenticationPopup = function (flag, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {
            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.enableAuthenticationPopup = flag;

    this._invoke("ETC_EnableAuthenticationPopup", params, invokeCallback);
};



/**
 * @public
 * @instance
 * @memberOf SConnect.PKCS11 
 * @function ETC_GetRetryCounter
 * @desc Retrieves the user PIN retry counter.
 * @param {number} sessionHandle    session identifier.
 * @param {object} callback object called when the operation is finished.
 * <ul>
 *   <li> callback.success(status, data) - function called when the function completed successfully</li>
 *   <li> callback.error(errorcode) - function called when the function failed</li>
 * </ul>
 * @return The success callback returns a property 'ETCKA_RETRY_USER' containing the user's PIN retry counter as a number.
 * @example
var callback = {
        success : function (status, data) {
            alert("The retry counter is " + data.ETCKA_RETRY_USER);
        },
        error : function (errorCode) {
            alert("The function failed with code (" + errorCode + ")");
        }
    },
    flag = false;
    
theObjectPKCS11.ETC_GetRetryCounter(sessionHandle, callback);                                        
 */
SConnect.PKCS11.prototype.ETC_GetRetryCounter = function (sessionHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {
            success: function (status, data) {
                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {
                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;

    this._invoke("ETC_GetRetryCounter", params, invokeCallback);
};




/**
 * @public
 * @description Creates the PKCS11 add-on instance. The returned instance by the 'success' callback exposes the PKCS11 API to the web application.
 *
 * @memberOf SConnect.PKCS11
 * @param {Object} callback object called when the operation is finished
 * <ul>
 *   <li> callback.success(pkcs11) - function called when SConnect PKCS11 add-on instance creation is successful
 *   <li> callback.error(errorcode) - function called when SConnect PKCS11 add-on instance creation is failed
 * </ul>
 * @example
 
 // Define a global PKCS11 object instance to use in the web application
 var theObjectPKCS11 = null,
    // Define the server configuration to use by SConnect to check or get SConnect installers and add-ons
    // In this example the SConnect component are stored at the URL "https://your-web-server-url/path-to-your-SConnect-repository"
    serverConfiguration = {
        // Mind to modify the URL to connect to your web server.
        // THE "impPath", "extPath", "eulaPath", "faqPath" AND "addonPath" URLS ARE ALWAYS ABSOLUTE PATH.
        imgPath: "https://your-web-server-url/path-to-your-SConnect-repository/images/",
        extPath: "https://your-web-server-url/path-to-your-SConnect-repository/extensions/",
        eulaPath: "https://your-web-server-url/path-to-your-SConnect-repository/eula/",
        faqPath: "https://your-web-server-url/path-to-your-SConnect-repository/faq/",
        addonPath: "https://your-web-server-url/path-to-your-SConnect-repository/addons/"
        // Mind to modify the licensePath URL accordingdly to your web server.
        // THE LICENSE PATH IS ALWAYS RELATIVE PATH.
        //,licensePath : "/sconnect.lic"
    };

 var initializeCallback = {

    success: function (status, data) {

        'use strict';
        alert("SConnect installed, PKCS11 add-on installed and C_Initialize succeeded");
         SConnect.PKCS11.StartTokenEventHandler(tokenEventCallback);
    },

    error: function (status) {
        'use strict';
        log("C_Initialize failed with status " + status);
    }
};

var finalizeCallback = {

    success: function (status, data) {

        'use strict';
        // C_Finalize done !
    },

    error: function (status) {
        'use strict';
        alert("C_Finalize failed with status " + status);
    }
};

var createCallback = {

    success: function (p11) {
        'use strict';
        theObjectPKCS11 = p11;

        theObjectPKCS11.C_Initialize(initializeCallback);
    },

    error: function (code) {
        'use strict';
        log('failed to create sac instance, reason: ' + code);
    }
};

var tokenEventCallback = {

    onTokenInsertion: function (resp) {
        'use strict';
        log('onTokenInsertion - slotId (' + resp.slotId + ')');
        log('onTokenInsertion - label (' + resp.label + ')');
    },

    onTokenRemoval: function (resp) {
        'use strict';
        log('onTokenRemoval - slotId (' + resp.slotId + ')');
        log('onTokenRemoval - label (' + resp.label + ')');
    }
};



var installAddOnsCallback = {

    success: function () {

        'use strict';
        SConnect.PKCS11.Create(createCallback);
    },

    error: function (code, info) {
        'use strict';
        alert('install-addons-failed, reason: ' + code);
    }
};

var validateCallback = {

    success: function () {
        'use strict';
        SConnect.InstallAddOns([new SConnect.PKCS11Info()], installAddOnsCallback);
    },

    error: function (code) {
        'use strict';
        alert('validate-server-failed, reason: ' + code);
    }
};

function onPageLoad() {

    'use strict';

    var installCallback = {

        success: function () {
            SConnect.ValidateServer(validateCallback);
        },

        error: function (code) {
            alert('sconnect-install-failed, reason: ' + code);
        }
    };

    // Configure the path to reach the SConnect components
    SConnect.ConfigResources(serverConfiguration);

    // Start the SConnect initialization or the automatic installation if SConnect is not installed on the end-user computer
    SConnect.Install(installCallback);
}


//Releases all SConnect & PKCS11 resources
function onPageUnload() {

    'use strict';

    // Stop the PKCS11 event handler
    SConnect.PKCS11.StopTokenEventHandler();

    // Release the PKCS11 object
    if (theObjectPKCS11) {
        theObjectPKCS11.C_Finalize(finalizeCallback);
        theObjectPKCS11.dispose();
    }
}


// Initialize the SConnect & PKCS11 addon when the web page is load
window.onload = onPageLoad;


// Release all resources when the page is unload
window.onunload = onPageUnload;
 */
SConnect.PKCS11.Create = function (callback) {

    'use strict';
    var info = new SConnect.PKCS11Info(),
        pkcs11 = new SConnect.PKCS11(),
        createCallback = {

            success: function (res) {

                var code = res[0],
                    success = (code >= 0);

                if (!success) {

                    pkcs11._triggerCallback(callback, false, code);
                } else {

                    pkcs11.addonId = res[0];
                    pkcs11.isDisposed = false;

                    pkcs11._triggerCallback(callback, true, pkcs11);

                }
            },
            error: function (code) {

                pkcs11._triggerCallback(callback, false, code);
            }
        };
    pkcs11.addonInfo = info;
    pkcs11.createInstance(createCallback);
};


/**
 * @public
 * @description Starts the listener to the token status change events. <strong>This function must be invoked after C_Initialize</strong> 
 * @memberOf SConnect.PKCS11
 * @param {Object} callback object called when the event is fired
 * <ul>
 *   <li> callback.onTokenInsertion(token) - function called when a token insertion event is fired
 *   <li> callback.onTokenRemoval(token) - function called when a token removal event is fired
 * </ul>
 * @example 
 var tokenEventCallback = {

    onTokenInsertion: function (resp) {
        'use strict';
        log('onTokenInsertion - slotId (' + resp.slotId + ')');
        log('onTokenInsertion - label (' + resp.label + ')');
    },

    onTokenRemoval: function (resp) {
        'use strict';
        log('onTokenRemoval - slotId (' + resp.slotId + ')');
        log('onTokenRemoval - label (' + resp.label + ')');
    }
};

SConnect.PKCS11.StartTokenEventHandler(tokenEventCallback);
*/
SConnect.PKCS11.StartTokenEventHandler = function (eventCallback, completionCallback) {

    'use strict';
    if (!window.internal_pkcs11_ir_scom) {

        // Prepare a callback to register the token/slot event status listener into
        var createCallback = {

            success: function (pkcs11) {

                // The new instance is created.
                // Create global objects to manage the asynchronous events that will be fired by the SConnect extension.
                window.internal_pkcs11_ir_scom = pkcs11;
                window.internal_pkcs11_ir_callback = eventCallback;

                // Prepare a callback to track the result of the registration
                var registerTokenStatusChangeListenerCallback = {
                    success: function (status) {

                        LoggingService.debug("registerTokenStatusChangeListenerCallback.success");
                        SConnect._triggerCallback(completionCallback, true, status);
                    },
                    error: function (status) {

                        LoggingService.error("registerTokenStatusChangeListenerCallback.error");
                        SConnect._triggerCallback(completionCallback, false, status);
                    }
                };

                pkcs11.registerTokenStatusChangeListener(SConnect.PKCS11.onTokenStatusChange, registerTokenStatusChangeListenerCallback);
            },
            error: function (status) {

                SConnect._triggerCallback(completionCallback, false, status);
            }
        };

        // Create a specific instance to manage in a separate thread the token/slot events
        SConnect.PKCS11.Create(createCallback);

    } else {

        SConnect._triggerCallback(completionCallback, true);
    }
};


/**
 * @public
 * @description Stops the listener to the token status change event. This function must be invoked before C_Finalize.
 * @memberOf SConnect.PKCS11
 * @param {Object} callback object called when the event is fired
 * <ul>
 *   <li> callback.success() - function called when listener unregistration is successful
 *   <li> callback.error(errorcode) - function called when listener unregistration is failed
 * </ul> 
 */
SConnect.PKCS11.StopTokenEventHandler = function (callback) {

    'use strict';
    if (window.internal_pkcs11_ir_scom) {

        window.internal_pkcs11_ir_scom.unregisterTokenStatusChangeListener(callback);
    } else {

        SConnect._triggerCallback(callback, true);
    }
};



/**
 * @private
 * @description Reports the slot events after the function StartTokenEventHandler is invoked and until the function StopTokenEventHandler is invoked.
 */
SConnect.PKCS11.onTokenStatusChange = function (event) {

    'use strict';
    if (event && event.length > 0) {

        var eventProperties = JSON.parse(event);

        LoggingService.debug(" == token status changed - label (" + eventProperties.label + ") - id (" + eventProperties.slotId + ") - status (" + eventProperties.status + ")");

        if (eventProperties.status === "removed") {

            // fire the token removal event
            if (window.internal_pkcs11_ir_callback) {
                if (window.internal_pkcs11_ir_callback.onTokenRemoval) {
                    window.internal_pkcs11_ir_callback.onTokenRemoval(eventProperties);
                }
            }
        } else if (eventProperties.status === "inserted") {

            // fire the insertion event
            if (window.internal_pkcs11_ir_callback) {
                if (window.internal_pkcs11_ir_callback.onTokenInsertion) {
                    window.internal_pkcs11_ir_callback.onTokenInsertion(eventProperties);
                }
            }
        }
    }
};


/**
* @public
* @memberOf SConnect.PKCS11 
* @function ETC_InitTokenInit
* @desc Initializes the token.
* @param {Number} slotId of the token's slot.
* @param {String} Label is the label to apply on the token formated as plain text.
* @param {String} pin is the security officer’s PIN formated as plain text.
* @param {String} retryCounter is a mandatory value between 0-15 coming from the GUI, not the token.
* @param {Object} callback object called when the operation is finished.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>*/
SConnect.PKCS11.prototype.ETC_InitTokenInit = function (slotId, label, pin, retryCounter, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.slotId = slotId;
    params.label = label;
    params.pin = pin;
    params.retryCounter = retryCounter;

    this._invoke("ETC_InitTokenInit", params, invokeCallback);
};

/**
* @public
* @memberOf SConnect.PKCS11 
* @function ETC_InitTokenFinal
* @desc Initializes the token.
* @param {Number} sessionHandle is the handle of the session.
* <ul>
*   <li> callback.success(status, data) - function called when the function completed successfully</li>
*   <li> callback.error(errorcode) - function called when the function failed</li>
* </ul>*/
SConnect.PKCS11.prototype.ETC_InitTokenFinal = function (sessionHandle, callback) {

    'use strict';

    var params = {},
        thisObject = this,
        invokeCallback = {

            success: function (status, data) {

                thisObject._triggerCallback(callback, true, status, data);
            },
            error: function (status) {

                thisObject._triggerCallback(callback, false, status);
            }
        };
    params.sessionHandle = sessionHandle;

    this._invoke("ETC_InitTokenFinal", params, invokeCallback);
};