Using the JAR Installation Manager to Install a PKCS #11 Cryptographic Module
[Contents]
Using the JAR Installation Manager to Install a PKCS #11 Cryptographic
Module
This document describes how to prepare a PKCS #11 cryptographic module
so that users can download it from the Internet, verify its integrity,
and install it, all with just a few mouse clicks. This document should
be used with Implementing
PKCS #11 for the Netscape Security Library.
Introduction
The packaged module that this document describes how to prepare is a signed
JAR file. This JAR file contains a dynamically linked library that implements
the security module and an installer script (.js) that installs,
registers, and configures the module.
SmartUpdate allows users to download a JAR file that has been digitally
signed by the software vendor. SmartUpdate then decompresses the JAR file,
verifies the digital signature, and verifies the integrity of the archived
files. If this verification process is successful, SmartUpdate runs
the installer script. The installer script instructs SmartUpdate to move
the downloaded cryptographic module library to a specified location, registers
the module with Navigator, and configures it.
This document does not describe how SmartUpdate works. For information
about SmartUpdate, see Using
JAR Installation Manager for SmartUpdate.
How to Create a Cryptographic Module JAR
-
Obtain a copy of PKCS
#11: Cryptographic Token Interface Standard, version 2.0, published
by RSA Laboratories, Redwood City, California.
-
Obtain a copy of Implementing
PKCS #11 for the Netscape Security Library.
-
Implement a PKCS #11 module according to PKCS #11 standards.
-
Write an installer script that registers the module with Navigator.
-
Use the Netscape Signing Tool (also known as "zigbert") to package the
module and the script in a signed JAR file.
-
Publish the JAR file on the web and inform users that they can use it to
install your module.
Sample Installer Script
The following installer script performs these actions:
-
Start SmartUpdate and declare the version and the name of the module to
be installed.
-
Based on the platform on which Navigator is running,
the script decides the name of the module to be extracted and its destination.
-
Extract a module called
dummy from the JAR file and copy it to
its destination.
Register the installed module by calling pkcs11.addmodule() method
with information about the capabilities of the module.
Check whether pkcs11.addmodule() has been successful and display
appropriate messages.
Since the script can figure out the module name at
time of installation, it is possible for vendors to package modules targeted
for different platforms inside the same JAR file. As a result, a single
JAR file may contain a common install script and various modules for HP-UX,
IRIX, MacOS, SunOS, Window 3.1, and so on. When users download a module,
they don't need to figure out which JAR file is appropriate for their computers,
because there is only one JAR file for all platforms. Of course,
the JAR file can grow very large, which may not be desirable for modem
users.
See Mechanism Flag Definitions for guidance on which
flags to set. Most tokens shouldn't set any of these flags.
////////////////////////////////////////////////////////////////////////////////////////
// Crypto Mechanism Flags
PKCS11_MECH_RSA_FLAG
= 0x1<<0;
PKCS11_MECH_DSA_FLAG
= 0x1<<1;
PKCS11_MECH_RC2_FLAG
= 0x1<<2;
PKCS11_MECH_RC4_FLAG
= 0x1<<3;
PKCS11_MECH_DES_FLAG
= 0x1<<4;
PKCS11_MECH_DH_FLAG
= 0x1<<5; //Diffie-Hellman
PKCS11_MECH_SKIPJACK_FLAG =
0x1<<6; //SKIPJACK algorithm as in Fortezza cards
PKCS11_MECH_RC5_FLAG
= 0x1<<7;
PKCS11_MECH_SHA1_FLAG
= 0x1<<8;
PKCS11_MECH_MD5_FLAG
= 0x1<<9;
PKCS11_MECH_MD2_FLAG
= 0x1<<10;
PKCS11_MECH_RANDOM_FLAG
= 0x1<<27; //Random number generator
PKCS11_PUB_READABLE_CERT_FLAG = 0x1<<28; //Stored
certs can be read off the token w/o logging in
PKCS11_DISABLE_FLAG
= 0x1<<30; //tell Navigator to disable this slot by default
// Important:
// 0x1<<11, 0x1<<12, ... , 0x1<<26, 0x1<<29,
and 0x1<<31 are reserved
// for internal use in Navigator.
// Therefore, these bits should always be set to 0; otherwise,
// Navigator might exhibit unpredictable behavior.
// These flags indicate which mechanisms should be turned on by
var pkcs11MechanismFlags = PKCS11_MECH_RANDOM_FLAG;
////////////////////////////////////////////////////////////////////////////////////////
// Ciphers that support SSL or S/MIME
PKCS11_CIPHER_FORTEZZA_FLAG = 0x1<<0;
// Important:
// 0x1<<1, 0x1<<2, ... , 0x1<<31 are reserved
// for internal use in Navigator.
// Therefore, these bits should ALWAYS be set to 0; otherwise,
// Navigator might exhibit unpredictable behavior.
// These flags indicate which SSL ciphers are supported
var pkcs11CipherFlags = PKCS11_CIPHER_FORTEZZA_FLAG;
////////////////////////////////////////////////////////////////////////////////////////
// Return values of pkcs11.addmodule() & pkcs11.delmodule()
// success codes
JS_OK_ADD_MODULE
= 3; // Successfully added a module
JS_OK_DEL_EXTERNAL_MODULE
= 2; // Successfully deleted ext. module
JS_OK_DEL_INTERNAL_MODULE
= 1; // Successfully deleted int. module
// failure codes
JS_ERR_OTHER
= -1; // Other errors than the followings
JS_ERR_USER_CANCEL_ACTION
= -2; // User abort an action
JS_ERR_INCORRECT_NUM_OF_ARGUMENTS= -3; // Calling a method w/ incorrect
# of arguments
JS_ERR_DEL_MODULE
= -4; // Error deleting a module
JS_ERR_ADD_MODULE
= -5; // Error adding a module
JS_ERR_BAD_MODULE_NAME
= -6; // The module name is invalid
JS_ERR_BAD_DLL_NAME
= -7; // The DLL name is bad
JS_ERR_BAD_MECHANISM_FLAGS
= -8; // The mechanism flags are invalid
JS_ERR_BAD_CIPHER_ENABLE_FLAGS = -9; // The SSL, S/MIME
cipher flags are invalid
JS_ERR_ADD_MODULE_DULICATE
=-10; // Module with the same name already installed
////////////////////////////////////////////////////////////////////////////////////////
// Find out which file is to be installed depending on the platform
// pathname seperator is platform specific
var sep = "/";
var vendor = "netscape";
var moduleName = "not_supported";
var plat = navigator.platform;
// destination of module
var dir = "pkcs11/" + vendor + "/" + plat + "/";
if (plat == "Win16") {
dir = "pkcs11/";
}
bAbort = false;
if (plat == "Win32") {
moduleName = "dummy32.dll";
sep = "\\";
} else if (plat == "Win16") {
moduleName = "dummy16.dll";
sep = "\\";
} else if (plat == "MacPPC") {
moduleName = "dummyLib";
sep = ":";
} else if (plat == "AIX4.1") {
moduleName = "dummy.a";
} else if (plat == "SunOS4.1.3_U1") {
moduleName = "dummy.so.1.0";
} else if ((plat == "SunOS5.4") || (plat == "SunOS5.5.1")){
moduleName = "dummy.so";
} else if ((plat == "HP-UXA.09") || (plat == "HP-UXB.10")){
moduleName = "dummy.sl";
} else {
window.alert("Sorry, platform "+plat+" is not
supported.");
bAbort = true;
}
////////////////////////////////////////////////////////////////////////////////////////
// Installation begins...
if (!bAbort) {
if (confirm("This script will install a cryptographic module. \nIt
may over-write older files having the same name. \nDo you want to continue?"))
{
// Step 1. Create a version object and a software update
object.
vi = new netscape.softupdate.VersionInfo(1, 1, 0, 0);
su = new netscape.softupdate.SoftwareUpdate(this, "Dummy
Card PKCS#11 Module");
// "Dummy ... Module" is the logical name of the bundle
////////////////////////////////////////
// Step 2. Start the install process.
bAbort = false;
err = su.StartInstall("NSDummy", // NSDummy is the component
folder (logical).
vi,
netscape.softupdate.SoftwareUpdate.FULL_INSTALL);
bAbort = (err!=0);
if (err == 0) {
////////////////////////////////////////
// Step 3. Find out the physical location of
the Program dir.
Folder = su.GetFolder("Program");
////////////////////////////////////////
// Step 4. Install the files. Unpack them and
list where they go.
err = su.AddSubcomponent("DummyLibrary_"+plat,
//component name (logical)
vi, // version info
moduleName, // source file in JAR (physical)
Folder, // target folder (physical)
dir + moduleName, // target path & filename (physical)
true); // forces update
if (err != 0) {
if (err == -200) {
errmsg = "Bad Package Name.";
} else if (err == -201)
{
errmsg = "Unexpected error.";
} else if (err == -203)
{
errmsg = "Installation script was signed by more than one certificate.";
} else if (err == -204)
{
errmsg = "Installation script was not signed."
} else if (err == -205)
{
errmsg = "The file to be installed is not signed."
} else if (err == -206)
{
errmsg = "The file to be installed is not present, or signed with a different
certificate than the one used to sign the install script."
} else if (err == -207)
{
errmsg = "JAR archive has not been opened."
} else if (err == -208)
{
errmsg = "Bad arguments to AddSubcomponent( )."
} else if (err == -209)
{
errmsg = "Illegal relative path."
} else if (err == -210)
{
errmsg = "User cancelled installation."
} else if (err == -211)
{
errmsg = "A problem occurred with the StartInstall( )."
} else {
errmsg = "Unknown error";
}
window.alert("Error
adding sub-component: "+"("+err+")"+errmsg);
bAbort = true;
}
}
////////////////////////////////////////
// Step 5. Unless there was a problem, move files to final
location
// and update the Client Version Registry.
if (bAbort) {
su.AbortInstall();
} else {
err = su.FinalizeInstall();
if (err != 0) {
if (err == -900) {
errmsg = "Restart the computer, and install again.";
} else if (err == -201)
{
errmsg = "Unexpected error.";
} else if (err == -202)
{
errmsg = "Access denied. Make sure you have the permissions to write to
the disk.";
} else if (err == -203)
{
errmsg = "Installation script was signed by more than one certificate.";
} else if (err == -204)
{
errmsg = "Installation script was not signed."
} else if (err == -205)
{
errmsg = "The file to be installed is not signed."
} else if (err == -206)
{
errmsg = "The file to be installed is not present, or it is signed with
a different certificate than the one used to sign the installation script."
} else if (err == -207)
{
errmsg = "JAR archive has not been opened."
} else if (err == -208)
{
errmsg = "Bad arguments to AddSubcomponent( )."
} else if (err == -209)
{
errmsg = "Illegal relative path( )."
} else if (err == -210)
{
errmsg = "User cancelled installation."
} else if (err == -211)
{
errmsg = "A problem occurred with the StartInstall( )."
} else {
errmsg = "\nIf you already have Dummy module installed, try deleting it
first.";
}
window.alert("Error
Finalizing Install: "+"("+err+")"+errmsg);
} else {
// Platform specific
full path
if (plat=="Win16") {
fullpath = Folder + "pkcs11" + sep + moduleName;
} else {
fullpath = Folder + "pkcs11" + sep + vendor + sep + plat + sep +
moduleName;
}
////////////////////////////////////////
// Step 6: Call pkcs11.addmodule()
to register the newly downloaded module
moduleCommonName = "Netscape
Dummy Module " + plat;
result = pkcs11.addmodule(moduleCommonName,
fullpath,
pkcs11MechanismFlags,
pkcs11CipherFlags);
if (result == -10) {
window.alert("New
module was copied to destination, \nbut setup failed because a module "
+"having the same name has been installed. \nTry deleting the module "
+ moduleCommonName +" first.")
} else if (result < 0)
{
window.alert("New
module was copied to destination, but setup failed. Error code: "
+ result);
}
}
}
}
}
Programmer's Reference
This section documents two functions:
addmodule
Adds a PKCS#11 cryptographic module to the cryptographic module database
and notifies Communicator which cryptographic mechanisms should be turned
on by default and which SSL or S/MIME ciphers are supported. For security
reasons, it displays a dialog box to ask the user to confirm this action.It
might display other dialog boxes if necessary.
Method of
pkcs11
Syntax
int pkcs11.addmodule(string ModuleName,
string LibraryFullPath,
int CryptoMechanismFlags,
int CipherFlags);
Parameters
ModuleName |
Name of the module. |
LibraryFullPath |
The filename of the library prepended with its full path. |
CryptoMechanismFlags |
A bit vector indicating all cryptographic mechanisms should be turned
on by default (see below). |
CipherFlags |
A bit vector indicating all SSL or S/MIME cipher functions supported
by the module (see below). |
NOTE: See Mechanism Flag Definitions for which flags
to set. Most tokens shouldn't set any of these flags.
Cryptographic Mechanism Flags
PKCS11_MECH_RSA_FLAG
= 0x1<<0;
PKCS11_MECH_DSA_FLAG
= 0x1<<1;
PKCS11_MECH_RC2_FLAG
= 0x1<<2;
PKCS11_MECH_RC4_FLAG
= 0x1<<3;
PKCS11_MECH_DES_FLAG
= 0x1<<4;
PKCS11_MECH_DH_FLAG
= 0x1<<5; //Diffie-Hellman
PKCS11_MECH_SKIPJACK_FLAG =
0x1<<6; //SKIPJACK algorithm as in Fortezza cards
PKCS11_MECH_RC5_FLAG
= 0x1<<7;
PKCS11_MECH_SHA1_FLAG
= 0x1<<8;
PKCS11_MECH_MD5_FLAG
= 0x1<<9;
PKCS11_MECH_MD2_FLAG
= 0x1<<10;
PKCS11_MECH_RANDOM_FLAG
= 0x1<<27; //Random number generator
PKCS11_PUB_READABLE_CERT_FLAG = 0x1<<28; //Stored
certs can be read off the token w/o logging in
PKCS11_DISABLE_FLAG
= 0x1<<30; //tell Navigator to disable this slot by default
Supported SSL or S/MIME Ciphers
PKCS11_CIPHER_FORTEZZA_FLAG = 0x1<<0;
Important for CryptoMechanismFlags
0x1<<11, 0x1<<12, ... , 0x1<<26,
0x1<<29, and 0x1<<31 are reserved for internal
use in Navigator.
Therefore, these bits should always be set to 0; otherwise, Navigator
might exhibit unpredictable behavior.
Important for CipherFlags
0x1<<1, 0x1<<2, ... , 0x1<<31
are reserved for internal use in Navigator.
Therefore, these bits should always be set to 0; otherwise,
Navigator might exhibit unpredictable behavior.
Example of CryptoMechanismFlags and CipherFlags
pkcs11MechanismFlags = PKCS11_MECH_DSA_FLAG | PKCS11_MECH_SKIPJACK_FLAG
| PKCS11_MECH_RANDOM_FLAG;
pkcs11CipherFlags = PKCS11_CIPHER_FORTEZZA_FLAG;
Return Values
// Return values of pkcs11.addmod()
// success codes
JS_OK_ADD_MODULE
= 3 // Successfully added a module
// failure codes
JS_ERR_OTHER
= -1 // Errors other than the following
JS_ERR_USER_CANCEL_ACTION
= -2 // User abort an action
JS_ERR_INCORRECT_NUM_OF_ARGUMENTS= -3 // Calling a method w/ incorrect
# of arguments
JS_ERR_ADD_MODULE
= -5 // Error adding a module
JS_ERR_BAD_MODULE_NAME
= -6 // The module name is invalid
JS_ERR_BAD_DLL_NAME
= -7 // The DLL name is bad
JS_ERR_BAD_MECHANISM_FLAGS
= -8 // The mechanism flags are invalid
JS_ERR_BAD_CIPHER_ENABLE_FLAGS = -9 // The SSL, S/MIME
cipher flags are invalid
JS_ERR_ADD_MODULE_DUPLICATE
=-10 // The module being installed has the same name as
// one of the modules that has already been installed
delmodule
Deletes a PKCS #11 cryptographic module from the module database, but does
not physically remove the file. For security reasons, it will display a
dialog box to ask the user to confirm this action. It may display other
dialog boxes if necessary.
Method of
pkcs11
Syntax
int pkcs11.delmodule(string ModuleName);
Parameter
ModuleName |
Name of the module |
Return Values
// Return values of pkcs11.addmod() & pkcs11.delmod()
// success codes
JS_OK_DEL_EXTERNAL_MODULE
= 2 // Successfully deleted ext. module
JS_OK_DEL_INTERNAL_MODULE
= 1 // Successfully deleted int. module
// failure codes
JS_ERR_OTHER
= -1 // Other errors than the followings
JS_ERR_USER_CANCEL_ACTION
= -2 // User abort an action
JS_ERR_INCORRECT_NUM_OF_ARGUMENTS= -3 // Calling a method w/ incorrect
# of arguments
JS_ERR_DEL_MODULE
= -4 // Error deleting a module
JS_ERR_BAD_MODULE_NAME
= -6 // The module name is invalid
Mechanism Flag Definitions
In general, most tokens should not set any of the cipher flags. Setting
these flags means you want your token to supply the default implementation
for these functions. Normally Communicator uses its own internal module
to supply these functions. These flags override that preference. If you
choose to implement these flags, your module must supply the following
additional functions for each flag:
PKCS11_MECH_FLAG: must support CKM_RSA_PKCS and CKM_RSA_X_509 and
the following functions: C_WRAPKEY, C_ENCRYPT, C_SIGN, C_DECRYPT, C_UNWRAPKEY,
C_VERIFYRECOVER, C_VERIFY, C_GENERATEKEYPAIR (2048, 1024, 512) size
PKCS11_MECH_DSA_FLAG: must support CKM_DSA and the following functions:
C_SIGN, C_VERIFY, C_GENERATEKEYPAIR
PKCS11_MECH_RC2_FLAG: must support CKM_RC2_CBC and CKM_RC2_ECB and
the following functions: C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY,
C_UNWRAPKEY
PKCS11_MECH_RC4_FLAG: must support CKM_RC4_CBC and CKM_RC4_ECB and
the following functions: C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY,
C_UNWRAPKEY
PKCS11_MECH_DES_FLAG: must support CKM_CPMF_CBC, CKM_DES_CBC, CKM_DES3_CBC,
CKM_CPMF_ECB, CKM_DES_ECB, CKM_DES3_ECB and the following functions: C_GENERATEKEY,
C_ENCRYPT, C_DECRYPT, C_WRAPKEY, C_UNWRAPKEY
PKCS11_MECH_DH_FLAG: must support CKM_DH_PKCS_DERIVE and CKM_DH_KEY_PAIR_GEN
and the following functions: C_DERIVEKEY, C_GENERATEKEYPAIR
PKCS11_SKIPJACK_FLAG: CKM_SKIPJACK_CBC64 and the following functions:
C_GENERATEKEY, C_ENCRYPT, C_DECRYPT, C_WRAPKEY, C_UNWRAPKEY
PKCS11_MECH_MD5_FLAG: Hashing must be able to function without authentication.
PKCS11_MECH_SHA1_FLAG: Hashing must be able to function without
authentication.
PKCS11_MECH_MD2_FLAG: Hashing must be able to function without authentication.
PKCS11_RANDOM_FLAG: Use token's Random Number Generator.
Warning: Must be able to use without authentication. Many hardware
random number generators are not as secure as the Netscape internal one.
Do not select this value unless you can show that your random number generator
is secure. Even so, it's highly discouraged.
PKCS11_PUB_READABLE_CERT_FLAG: This is the only flag most smart
tokens should turn on. You can turn this flag on if:
1) the certs on your token can be read without authentication and,
2) the public key on your token can be found by ID, MODULUS, or
VALUE and all your private keys have the associated public key.
Turning this flag on will illuminate a large number of password
prompts for your token when looking up certs in Communicator.
Last Updated: 12/08/97
Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use