You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is
highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If
there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.
/* Example code to illustrate generation of a secret symmetric key ring
* that PERSISTS in the NSS database. The symmetric keys can then be
used
* without ever exposing them in the clear.
*
* To encrypt, you need the id of the key to use.
* To decrypt, you need the ciphertext and the id of the key that was
used
* to encrypt
*
* Before running this example, create the NSS database
* certutil -N -d .
* (enter "test" when prompted for password)
*/
#include "nss.h"
#include "pk11func.h"
/* the key id can be any sequence of bytes. this example happens to use an
* integer */
void genkey(int id);
/* this callback is responsible for returning the password to the NSS
* key database. for example purposes, this function hardcodes the password.
* In a real app, this function should obtain the password using secure
means
* such as prompting an operator, or retrieving it over a secure communication
* channel
*/
char *passwdcb(PK11SlotInfo *info, PRBool retry, void *arg);
int main(int argc, char **argv)
{
SECStatus rv;
/* Initialize NSS */
PK11_SetPasswordFunc(passwdcb);
/* The NSS db must be initialized read-write since we'll be creating
* keys in it. Once keys are generated, it can be opened without
read-write
* subsequently (NSS_Init).
*/
rv = NSS_InitReadWrite(".");
if (rv != SECSuccess)
{
fprintf(stderr, "NSS initialization failed (err %d)\n",
PR_GetError());
exit(1);
}
/* generate a key with id 1. should succeed on first run on a fresh
db,
* should fail on successive runs because key with that id already
exists */
genkey(1);
/* generate a key with id 2. should succeed on first run on a fresh
db,
* should fail on successive runs because key with that id already
exists */
genkey(2);
/* generate a key with id 1 - this will fail because key with that
id
* already exists */
genkey(1);
}
void genkey(int id)
{
PK11SlotInfo* slot = NULL;
PK11SymKey* key = NULL;
SECItem keyiditem;
int
keyid[1];
CK_MECHANISM_TYPE cipherMech;
/* using CKM_AES_CBC_PAD mechanism for example */
cipherMech = CKM_AES_CBC_PAD;
slot = PK11_GetInternalKeySlot();
/* slot = PK11_GetBestSlot(cipherMech, NULL); didn't work.
* Error code: token is read-only. ??
*/
if (slot == NULL)
{
fprintf(stderr, "Unable to find security device (err %d)\n",
PR_GetError());
return;
}
keyid[0] = id;
keyiditem.type = 0;
keyiditem.data = (void *)keyid;
keyiditem.len = sizeof(keyid[0]);
/* Note: keysize must be 0 for fixed key-length algorithms like DES.
* Since we're using AES
in this example, we're specifying
* one of the valid keysizes
(16, 24, 32)
*/
key = PK11_TokenKeyGen(slot, cipherMech, 0, 32 /*keysize*/,
&keyiditem, PR_TRUE, 0);
if (key == NULL)
{
fprintf(stderr, "PK11_TokenKeyGen failed (err %d)\n",
PR_GetError());
PK11_FreeSlot(slot);
return;
}
fprintf(stderr, "key length of generated key is %d\n",
PK11_GetKeyLength(key));
fprintf(stderr, "mechanism of key is %d (asked for %d)\n",
PK11_GetMechanism(key),
cipherMech);
PK11_FreeSymKey(key);
key = PK11_FindFixedKey(slot, cipherMech, &keyiditem, 0);
if (key == NULL)
{
fprintf(stderr, "PK11_FindFixedKey failed (err %d)\n",
PR_GetError());
PK11_FreeSlot(slot);
return;
}
fprintf(stderr, "Found key!\n");
fprintf(stderr, "key length of generated key is %d\n",
PK11_GetKeyLength(key));
fprintf(stderr, "mechanism of key is %d (asked for %d)\n",
PK11_GetMechanism(key),
cipherMech);
PK11_FreeSymKey(key);
PK11_FreeSlot(slot);
}
char *passwdcb(PK11SlotInfo *info, PRBool retry, void *arg)
{
if (!retry)
return PL_strdup("test");
else
return NULL;
}