clean up algparam implementation STAN_WORK_BRANCH
authorian.mcgreer%sun.com
Mon, 07 Oct 2002 19:44:42 +0000
branchSTAN_WORK_BRANCH
changeset 3688 71cb6d7e0592ed61c65c715c1fcc947d9e8c6dfa
parent 3616 b14273d5d42f1f4df8993c1694b3acf95b5f9e69
child 3716 6acb5f6ee8a9226bf71484741893f99041f9084a
push idunknown
push userunknown
push dateunknown
clean up algparam implementation implement SSL key derivation methods for tokens implement random seed/generation methods for tokens
security/nss/lib/base/nsserrors.h
security/nss/lib/dev/algparam.c
security/nss/lib/dev/ckhelper.c
security/nss/lib/dev/dev.h
security/nss/lib/dev/devm.h
security/nss/lib/dev/devtoken.c
security/nss/lib/dev/nssdev.h
security/nss/lib/dev/nssdevt.h
--- a/security/nss/lib/base/nsserrors.h
+++ b/security/nss/lib/base/nsserrors.h
@@ -67,18 +67,20 @@ static const char NSSERRORS_CVS_ID[] = "
 
 #define NSS_ERROR_INVALID_PASSWORD                          28
 #define NSS_ERROR_USER_CANCELED                             29
 
 #define NSS_ERROR_MAXIMUM_FOUND                             30
 #define NSS_ERROR_INVALID_SIGNATURE                         31
 #define NSS_ERROR_INVALID_DATA                              32
 
-/* token errors */
-#define NSS_ERROR_TOKEN_FAILURE                            100
+/* token device errors */
+#define NSS_ERROR_INVALID_DEVICE                           100
+#define NSS_ERROR_DEVICE_ERROR                             101
+#define NSS_ERROR_DEVICE_REMOVED                           102
 
 /* certificate errors */
 #define NSS_ERROR_INVALID_CERTIFICATE                      500
 #define NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND             501
 #define NSS_ERROR_CERTIFICATE_USAGE_INSUFFICIENT           502
 #define NSS_ERROR_CERTIFICATE_EXCEEDED_PATH_LENGTH_CONSTRAINT 503
 #define NSS_ERROR_CERTIFICATE_HAS_NO_TRUSTED_ISSUER        504
 #define NSS_ERROR_CERTIFICATE_NOT_VALID_AT_TIME            505
--- a/security/nss/lib/dev/algparam.c
+++ b/security/nss/lib/dev/algparam.c
@@ -38,113 +38,186 @@ static const char CVS_ID[] = "@(#) $RCSf
 #ifndef DEVM_H
 #include "devm.h"
 #endif /* DEVM_H */
 
 #ifndef CKHELPER_H
 #include "ckhelper.h"
 #endif /* CKHELPER_H */
 
+#ifndef ASN1_H
+#include "asn1.h"
+#endif /* ASN1_H */
+
+/*
+ * NSSAlgorithmAndParametersStr
+ *
+ * This generic container should hold everything we need to know
+ * to use an algorithm, with the specific exclusion of keysizes when 
+ * doing key generation (this is specified in the API, thus the same
+ * AlgorithmAndParameters can be reused to generate keys of different
+ * length).
+ *
+ * Internally, we need to communicate the following information to
+ * Cryptoki:
+ *
+ * 1) a CK_MECHANISM
+ * 2) template values for key generation and derivation
+ *
+ * The CK_MECHANISM is always set when the AlgorithmAndParameters is
+ * created.  The template values are set upon request, and are extracted
+ * from the the params field.
+ *
+ * Once an AlgorithmAndParamters is created, it is considered read-only.
+ * Thus is it used as 'const' throughout the API.
+ *
+ * An AlgorithmAndParameters can be created the following ways:
+ *
+ * 1) from an { NSSAlgorithmType, NSSParameters } pair (generic crypto),
+ * 2) from an { NSSKeyPairType, NSSParameters } pair (key pair generation),
+ * 3) from an { NSSSymmetricKeyType, NSSParameters } pair (symkey gen),
+ * 4) from an { CK_MECHANISM_TYPE, NSSParameters } pair
+ *     --- this is a 'friendly' method used to convert OID's to Alg&Params
+ */
 struct NSSAlgorithmAndParametersStr
 {
   NSSArena *arena;
-  CK_MECHANISM mechanism;
-  NSSAlgorithmType algorithm;
-  NSSParameters params;
-  PRBool isKeyGen;
-  unsigned char rsape[4]; /* XXX hack to make RSA easier */
-};
-
-static const NSSAlgorithmAndParameters s_deskg = {
-  NULL,
-  { CKM_DES_KEY_GEN, NULL, 0 }
-};
-
-static const NSSAlgorithmAndParameters s_3deskg = {
-  NULL,
-  { CKM_DES3_KEY_GEN, NULL, 0 }
-};
+  CK_MECHANISM mechanism; /* alg&param in cryptoki terms */
+  NSSParameters params;   /* template values kept here */
 
-static const NSSAlgorithmAndParameters s_rc2kg = {
-  NULL,
-  { CKM_RC2_KEY_GEN, NULL, 0 }
-};
-
-static const NSSAlgorithmAndParameters s_rc4kg = {
-  NULL,
-  { CKM_RC4_KEY_GEN, NULL, 0 }
-};
-
-static const NSSAlgorithmAndParameters s_rc5kg = {
-  NULL,
-  { CKM_RC5_KEY_GEN, NULL, 0 }
-};
-
-static const NSSAlgorithmAndParameters s_aeskg = {
-  NULL,
-  { CKM_AES_KEY_GEN, NULL, 0 }
+  /* every happy algorithm sets a mechanism the same way, but each
+   * unhappy one sets a template a different way.
+   */
+  PRIntn (* set_template)(const NSSAlgorithmAndParameters *ap,
+                          CK_ATTRIBUTE_PTR aTemplate,
+                          CK_ULONG templateSize);
 };
 
-static const NSSAlgorithmAndParameters s_md2 = {
-  NULL,
-  { CKM_MD2, NULL, 0 }
-};
-
-static const NSSAlgorithmAndParameters s_md5 = {
-  NULL,
-  { CKM_MD5, NULL, 0 }
-};
+/*
+ * For each algorithm that requires a parameter, the following methods
+ * may exist (depending on what kind of parameters it requires):
+ *
+ * set_xxx_mechanism -- convert an NSSParameters to a CK_MECHANISM
+ *                      for algorithm xxx
+ * xxx_settor -- callback function to set template values for xxx
+ * decode_xxx -- decode an octet string into parameters for
+ *               algorithm xxx (used when creating from OID's)
+ */
 
-const NSSAlgorithmAndParameters s_sha1 = {
-  NULL,
-  { CKM_SHA_1, NULL, 0 }
-};
+/* For all mechanisms where the only parameter is an IV */
+static PRStatus
+set_iv_parameter
+(
+  CK_MECHANISM_PTR mechPtr,
+  NSSItem *iv,
+  NSSArena *arena
+)
+{
+    mechPtr->pParameter = nss_ZAlloc(arena, iv->size);
+    if (!mechPtr->pParameter) {
+	return PR_FAILURE;
+    }
+    nsslibc_memcpy(mechPtr->pParameter, iv->data, iv->size);
+    mechPtr->ulParameterLen = iv->size;
+    return PR_SUCCESS;
+}
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_DESKeyGen = &s_deskg;
-
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_3DESKeyGen = &s_3deskg;
+/* For all mechanisms where the only parameter is a length in bits */
+static PRStatus
+set_bits_parameter
+(
+  CK_MECHANISM_PTR mechPtr,
+  PRUint32 numBits,
+  NSSArena *arena
+)
+{
+    CK_ULONG ulBits = numBits;
+    PRUint32 pLen = sizeof(CK_ULONG);
+    mechPtr->pParameter = nss_ZAlloc(arena, pLen);
+    if (!mechPtr->pParameter) {
+	return PR_FAILURE;
+    }
+    nsslibc_memcpy(mechPtr->pParameter, &ulBits, pLen);
+    mechPtr->ulParameterLen = pLen;
+    return PR_SUCCESS;
+}
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_RC2KeyGen = &s_rc2kg;
+/* For all mechanisms that don't need to set template values (default) */
+static PRIntn
+null_settor (
+  const NSSAlgorithmAndParameters *ap,
+  CK_ATTRIBUTE_PTR aTemplate,
+  CK_ULONG templateSize
+)
+{
+    return 0;
+}
+
+/*
+ * Decoding IV parameters
+ */
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_RC4KeyGen = &s_rc4kg;
+static PRStatus
+decode_iv(NSSAlgorithmAndParameters *ap, const NSSItem *params)
+{
+    PRStatus status;
+    NSSItem iv;
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_RC5KeyGen = &s_rc5kg;
+    status = nssASN1_DecodeBER(ap->arena, &iv, 
+                               nssASN1Template_OctetString, params);
+    if (status == PR_SUCCESS) {
+	ap->mechanism.pParameter = iv.data;
+	ap->mechanism.ulParameterLen = iv.size;
+    }
+    return status;
+}
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_AESKeyGen = &s_aeskg;
-
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_MD2  = &s_md2;
+/*
+ * RSA key generation
+ */
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_MD5  = &s_md5;
+/* set template parameters for RSA key generation */
+static PRIntn
+rsa_keygen_settor (
+  const NSSAlgorithmAndParameters *ap,
+  CK_ATTRIBUTE_PTR aTemplate,
+  CK_ULONG templateSize
+)
+{
+    PRUint32 rsape;
+    CK_ATTRIBUTE_PTR attr = aTemplate;
+    /* N */
+    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_MODULUS_BITS,
+                             ap->params.rsakg.modulusBits);
+    /* e */
+    rsape = PR_htonl(ap->params.rsakg.publicExponent);
+    attr->type = CKA_PUBLIC_EXPONENT; 
+    attr->pValue = (CK_BYTE_PTR)rsape;
+    attr->ulValueLen = sizeof(rsape);
+    attr++;
+    return attr - aTemplate;
+}
 
-NSS_IMPLEMENT_DATA const NSSAlgorithmAndParameters *
-                    NSSAlgorithmAndParameters_SHA1 = &s_sha1;
-
+/* 
+ * RSA cipher
+ */
 static PRStatus
 set_rsa_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters
 )
 {
     NSSParameters defaultParams;
     if (!parameters) {
-	defaultParams.rsa = NSSRSABlockFormat_RAW;
+	defaultParams.rsa = NSSRSABlockFormat_Raw;
 	parameters = &defaultParams;
     }
     switch (parameters->rsa) {
-    case NSSRSABlockFormat_RAW:
+    case NSSRSABlockFormat_Raw:
 	mechPtr->mechanism = CKM_RSA_X_509;
 	break;
     case NSSRSABlockFormat_PKCS1:
 	mechPtr->mechanism = CKM_RSA_PKCS;
 	break;
     case NSSRSABlockFormat_PKCS1_WITH_MD2:
 	mechPtr->mechanism = CKM_MD2_RSA_PKCS;
 	break;
@@ -158,21 +231,50 @@ set_rsa_mechanism
 	mechPtr->mechanism = CKM_RSA_PKCS_OAEP;
 	break;
     default:
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
+/* 
+ * DSA key generation
+ */
+
+/* set template parameters for DSA key generation */
+static PRIntn
+dsa_keygen_settor (
+  const NSSAlgorithmAndParameters *ap,
+  CK_ATTRIBUTE_PTR aTemplate,
+  CK_ULONG templateSize
+)
+{
+    CK_ATTRIBUTE_PTR attr = aTemplate;
+    if (ap->params.dsakg.p.data == NULL) {
+	/* XXX ? */
+	PR_ASSERT(0);
+    } else {
+	/* P */
+	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_PRIME, &ap->params.dsakg.p);
+	/* Q */
+	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBPRIME, &ap->params.dsakg.q);
+	/* G */
+	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_BASE, &ap->params.dsakg.g);
+    }
+    return attr - aTemplate;
+}
+
+/*
+ * DSA cipher
+ */
 static PRStatus
 set_dsa_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters
 )
 {
     NSSParameters defaultParams;
     if (!parameters) {
 	defaultParams.dsa = NSSAlgorithmType_NULL;
 	parameters = &defaultParams;
     }
@@ -184,68 +286,65 @@ set_dsa_mechanism
 	mechPtr->mechanism = CKM_DSA_SHA1;
 	break;
     default:
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
+/*
+ * Diffie-Hellman key generation
+ */
+
+/* set template parameters for Diffie-Hellman key generation */
+static PRIntn
+dh_keygen_settor (
+  const NSSAlgorithmAndParameters *ap,
+  CK_ATTRIBUTE_PTR aTemplate,
+  CK_ULONG templateSize
+)
+{
+    CK_ATTRIBUTE_PTR attr = aTemplate;
+    if (ap->params.dhkg.p.data == NULL) {
+	/* XXX ? */
+	PR_ASSERT(0);
+    } else {
+	/* P */
+	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_PRIME, &ap->params.dhkg.p);
+	/* G */
+	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_BASE, &ap->params.dhkg.g);
+	/* constraint on private value */
+	NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_VALUE_BITS,
+	                         ap->params.dhkg.valueBits);
+    }
+    return attr - aTemplate;
+}
+
+/*
+ * Diffie-Hellman key derivation
+ */
 static PRStatus
 set_dh_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters
 )
 {
-    return PR_SUCCESS;
-}
-
-static PRStatus
-set_iv_parameter
-(
-  CK_MECHANISM_PTR mechPtr,
-  NSSItem *iv,
-  NSSArena *arena
-)
-{
-    mechPtr->pParameter = nss_ZAlloc(arena, iv->size);
-    if (!mechPtr->pParameter) {
-	return PR_FAILURE;
-    }
-    nsslibc_memcpy(mechPtr->pParameter, iv->data, iv->size);
-    mechPtr->ulParameterLen = iv->size;
-    return PR_SUCCESS;
+	/* XXX */
+    return PR_FAILURE;
 }
 
-static PRStatus
-set_bits_parameter
-(
-  CK_MECHANISM_PTR mechPtr,
-  PRUint32 numBits,
-  NSSArena *arena
-)
-{
-    CK_ULONG ulBits = numBits;
-    PRUint32 pLen = sizeof(CK_ULONG);
-    mechPtr->pParameter = nss_ZAlloc(arena, pLen);
-    if (!mechPtr->pParameter) {
-	return PR_FAILURE;
-    }
-    nsslibc_memcpy(mechPtr->pParameter, &ulBits, pLen);
-    mechPtr->ulParameterLen = pLen;
-    return PR_SUCCESS;
-}
-
+/*
+ * DES
+ */
 static PRStatus
 set_des_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     if (parameters) {
 	if (parameters->des.pkcsPad) {
 	    mechPtr->mechanism = CKM_DES_CBC_PAD;
 	} else {
@@ -253,21 +352,23 @@ set_des_mechanism
 	}
 	return set_iv_parameter(mechPtr, &parameters->des.iv, arena);
     } else {
 	mechPtr->mechanism = CKM_DES_ECB;
     }
     return PR_SUCCESS;
 }
 
+/*
+ * Triple-DES
+ */
 static PRStatus
 set_des3_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     if (parameters) {
 	if (parameters->des.pkcsPad) {
 	    mechPtr->mechanism = CKM_DES3_CBC_PAD;
 	} else {
@@ -275,21 +376,23 @@ set_des3_mechanism
 	}
 	return set_iv_parameter(mechPtr, &parameters->des.iv, arena);
     } else {
 	mechPtr->mechanism = CKM_DES3_ECB;
     }
     return PR_SUCCESS;
 }
 
+/*
+ * AES
+ */
 static PRStatus
 set_aes_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     if (parameters) {
 	if (parameters->aes.pkcsPad) {
 	    mechPtr->mechanism = CKM_AES_CBC_PAD;
 	} else {
@@ -297,21 +400,26 @@ set_aes_mechanism
 	}
 	return set_iv_parameter(mechPtr, &parameters->des.iv, arena);
     } else {
 	mechPtr->mechanism = CKM_AES_ECB;
     }
     return PR_SUCCESS;
 }
 
+/*
+ * RC2
+ */
+
+/* setting mechanism */
+
 static PRStatus
 set_rc2_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     if (parameters) {
 	CK_RC2_CBC_PARAMS_PTR rc2p;
 	if (parameters->rc2.pkcsPad) {
 	    mechPtr->mechanism = CKM_RC2_CBC_PAD;
@@ -332,21 +440,115 @@ set_rc2_mechanism
 	mechPtr->mechanism = CKM_RC2_ECB;
 	return set_bits_parameter(mechPtr, 
 	                          parameters->rc2.effectiveKeySizeInBits, 
 	                          arena);
     }
     return PR_SUCCESS;
 }
 
+/* decoding */
+
+struct rc2_param_str {
+  NSSItem version; /* number? */
+  NSSItem iv;
+};
+
+static const nssASN1Template rc2_ecb_param_tmpl[] = {
+  { nssASN1_SEQUENCE, 0, NULL, sizeof(struct rc2_param_str)  },
+  { nssASN1_INTEGER, offsetof(struct rc2_param_str, version) },
+  { 0 }
+};
+
+static const nssASN1Template rc2_cbc_param_tmpl[] = {
+  { nssASN1_SEQUENCE, 0, NULL, sizeof(struct rc2_param_str)  },
+  { nssASN1_INTEGER, offsetof(struct rc2_param_str, version) },
+  { nssASN1_OCTET_STRING, offsetof(struct rc2_param_str, iv) },
+  { 0 }
+};
+
+static CK_ULONG rc2_map(NSSItem *version)
+{
+    PRStatus status;
+    PRUint32 x;
+    status = nssASN1_CreatePRUint32FromBER(version, &x);
+    if (status == PR_SUCCESS) {
+	switch (x) {
+	case 120: return  64;
+	case 160: return  40;
+	case 58:
+	default:  return 128;
+	}
+    }
+    return -1;
+}
+
+static PRStatus
+decode_rc2_ecb(NSSAlgorithmAndParameters *ap, const NSSItem *params)
+{
+    PRStatus status;
+    CK_RC2_PARAMS *ckrc2p;
+    struct rc2_param_str rc2p;
+
+    status = nssASN1_DecodeBER(ap->arena, &rc2p, rc2_ecb_param_tmpl, params);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+    ckrc2p = nss_ZNEW(ap->arena, CK_RC2_PARAMS);
+    if (!ckrc2p) {
+	return PR_FAILURE;
+    }
+    *ckrc2p = rc2_map(&rc2p.version);
+    if (*ckrc2p == (CK_ULONG)-1) {
+	return PR_FAILURE;
+    }
+    ap->mechanism.pParameter = (void *)ckrc2p;
+    ap->mechanism.ulParameterLen = sizeof(CK_RC2_PARAMS);
+    return PR_SUCCESS;
+}
+
+static PRStatus
+decode_rc2_cbc(NSSAlgorithmAndParameters *ap, const NSSItem *params)
+{
+    PRStatus status;
+    CK_RC2_CBC_PARAMS *ckrc2p;
+    struct rc2_param_str rc2p;
+
+    status = nssASN1_DecodeBER(ap->arena, &rc2p, rc2_cbc_param_tmpl, params);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+    ckrc2p = nss_ZNEW(ap->arena, CK_RC2_CBC_PARAMS);
+    if (!ckrc2p) {
+	return PR_FAILURE;
+    }
+    ckrc2p->ulEffectiveBits = rc2_map(&rc2p.version);
+    if (ckrc2p->ulEffectiveBits == (CK_ULONG)-1) {
+	return PR_FAILURE;
+    }
+
+    /* sanity check before copying iv */
+    PR_ASSERT(rc2p.iv.size == sizeof(ckrc2p->iv));
+    if (rc2p.iv.size != sizeof(ckrc2p->iv)) {
+	return PR_FAILURE;
+    }
+    nsslibc_memcpy(ckrc2p->iv, rc2p.iv.data, sizeof(ckrc2p->iv));
+
+    ap->mechanism.pParameter = (void *)ckrc2p;
+    ap->mechanism.ulParameterLen = sizeof(CK_RC2_CBC_PARAMS);
+    return PR_SUCCESS;
+}
+
+/*
+ * RC5
+ */
 static PRStatus
 set_rc5_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
-  NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     if (parameters) {
 	CK_RC5_CBC_PARAMS_PTR rc5p;
 	if (parameters->rc5.pkcsPad) {
 	    mechPtr->mechanism = CKM_RC5_CBC_PAD;
@@ -379,45 +581,199 @@ set_rc5_mechanism
 	rc5p->ulWordsize = parameters->rc5.wordSize;
 	rc5p->ulRounds = parameters->rc5.numRounds;
 	mechPtr->pParameter = rc5p;
 	mechPtr->ulParameterLen = sizeof(rc5p);
     }
     return PR_SUCCESS;
 }
 
+/*
+ * SSL algorithms
+ */
+
+/*
+ * SSL Pre-Master secret key generation
+ */
+static PRStatus
+set_sslpms_mechanism (
+  CK_MECHANISM_PTR mechPtr,
+  NSSParameters *parameters,
+  NSSArena *arena
+)
+{
+    CK_VERSION *sslVersion = NULL;
+    CK_VERSION sv;
+
+    switch (parameters->sslpms) {
+    case NSSSSLVersion_SSLv3: 
+	mechPtr->mechanism = CKM_SSL3_PRE_MASTER_KEY_GEN;
+	sv.major = 3; sv.minor = 0; break;
+    case NSSSSLVersion_TLS:   
+	mechPtr->mechanism = CKM_TLS_PRE_MASTER_KEY_GEN;
+	sv.major = 3; sv.minor = 1; break;
+    default:
+	/* XXX error invalid args */
+	return PR_FAILURE;
+    }
+
+    sslVersion = nss_ZNEW(arena, CK_VERSION);
+    if (!sslVersion) {
+	return PR_FAILURE;
+    }
+    *sslVersion = sv;
+
+    mechPtr->pParameter = sslVersion;
+    mechPtr->ulParameterLen = sizeof(CK_VERSION);
+    return PR_SUCCESS;
+}
+
+static PRStatus
+copy_item(NSSItem *it, CK_BYTE_PTR *buf, CK_ULONG *len, NSSArena *arena)
+{
+    *buf = nss_ZAlloc(arena, it->size);
+    if (*buf) {
+	nsslibc_memcpy(*buf, it->data, it->size);
+	*len = it->size;
+	return PR_SUCCESS;
+    }
+    return PR_FAILURE;
+}
+
+/*
+ * SSL Master secret key derivation
+ */
+static PRStatus
+set_sslms_mechanism (
+  CK_MECHANISM_PTR mechPtr,
+  NSSParameters *parameters,
+  NSSArena *arena
+)
+{
+    PRStatus status;
+    CK_VERSION sv;
+    CK_SSL3_MASTER_KEY_DERIVE_PARAMS *msp;
+
+    switch (parameters->sslms.version) {
+    case NSSSSLVersion_SSLv3: 
+	mechPtr->mechanism = CKM_SSL3_MASTER_KEY_DERIVE;
+	sv.major = 3; sv.minor = 0; break;
+    case NSSSSLVersion_TLS:   
+	mechPtr->mechanism = CKM_TLS_MASTER_KEY_DERIVE;
+	sv.major = 3; sv.minor = 1; break;
+    default:
+	/* XXX error invalid args */
+	return PR_FAILURE;
+    }
+
+    msp = nss_ZNEW(arena, CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
+    if (!msp) {
+	return PR_FAILURE;
+    }
+    msp->pVersion = nss_ZNEW(arena, CK_VERSION);
+    if (!msp->pVersion) {
+	return PR_FAILURE;
+    }
+    *msp->pVersion = sv;
+
+    status = copy_item(&parameters->sslms.clientRandom,
+                       &msp->RandomInfo.pClientRandom,
+                       &msp->RandomInfo.ulClientRandomLen, arena);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+
+    status = copy_item(&parameters->sslms.serverRandom,
+                       &msp->RandomInfo.pServerRandom,
+                       &msp->RandomInfo.ulServerRandomLen, arena);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+
+    mechPtr->pParameter = msp;
+    mechPtr->ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
+    return PR_SUCCESS;
+}
+
+/*
+ * SSL session secret keys derivation
+ */
+static PRStatus
+set_sslsession_derive_mechanism (
+  CK_MECHANISM_PTR mechPtr,
+  NSSSSLSessionParameters *parameters,
+  NSSArena *arena
+)
+{
+    PRStatus status;
+    CK_SSL3_KEY_MAT_PARAMS *kmp;
+
+    mechPtr->mechanism = CKM_SSL3_KEY_AND_MAC_DERIVE;
+
+    kmp = nss_ZNEW(arena, CK_SSL3_KEY_MAT_PARAMS);
+    if (!kmp) {
+	return PR_FAILURE;
+    }
+    kmp->ulMacSizeInBits = parameters->macSizeInBits;
+    kmp->ulKeySizeInBits = parameters->keySizeInBits;
+    kmp->ulIVSizeInBits = parameters->ivSizeInBits;
+    kmp->bIsExport = parameters->isExport;
+
+    status = copy_item(&parameters->clientRandom,
+                       &kmp->RandomInfo.pClientRandom,
+                       &kmp->RandomInfo.ulClientRandomLen, arena);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+
+    status = copy_item(&parameters->serverRandom,
+                       &kmp->RandomInfo.pServerRandom,
+                       &kmp->RandomInfo.ulServerRandomLen, arena);
+    if (status == PR_FAILURE) {
+	return PR_FAILURE;
+    }
+
+    mechPtr->pParameter = kmp;
+    mechPtr->ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+    return PR_SUCCESS;
+}
+
+/*
+ * convert and algorithm type and algorithm-specific parameters
+ * to a CK_MECHANISM.
+ */
 static PRStatus
 set_cryptoki_mechanism
 (
   CK_MECHANISM_PTR mechPtr,
   NSSAlgorithmType algorithm,
   NSSParameters *parameters,
   NSSArena *arena
 )
 {
     switch (algorithm) {
     case NSSAlgorithmType_RSA: 
-	return set_rsa_mechanism(mechPtr, algorithm, parameters);
+	return set_rsa_mechanism(mechPtr, parameters);
     case NSSAlgorithmType_DSA:
-	return set_dsa_mechanism(mechPtr, algorithm, parameters);
+	return set_dsa_mechanism(mechPtr, parameters);
     case NSSAlgorithmType_DH:
-	return set_dh_mechanism(mechPtr, algorithm, parameters);
+	return set_dh_mechanism(mechPtr, parameters);
     case NSSAlgorithmType_DES:
-	return set_des_mechanism(mechPtr, algorithm, parameters, arena);
+	return set_des_mechanism(mechPtr, parameters, arena);
     case NSSAlgorithmType_3DES:
-	return set_des3_mechanism(mechPtr, algorithm, parameters, arena);
+	return set_des3_mechanism(mechPtr, parameters, arena);
     case NSSAlgorithmType_AES:
-	return set_aes_mechanism(mechPtr, algorithm, parameters, arena);
+	return set_aes_mechanism(mechPtr, parameters, arena);
     case NSSAlgorithmType_RC2:
-	return set_rc2_mechanism(mechPtr, algorithm, parameters, arena);
+	return set_rc2_mechanism(mechPtr, parameters, arena);
     case NSSAlgorithmType_RC4:
 	mechPtr->mechanism = CKM_RC4;
 	break;
     case NSSAlgorithmType_RC5:
-	return set_rc5_mechanism(mechPtr, algorithm, parameters, arena);
+	return set_rc5_mechanism(mechPtr, parameters, arena);
     case NSSAlgorithmType_MD2:
 	mechPtr->mechanism = CKM_MD2;
 	break;
     case NSSAlgorithmType_MD5:
 	mechPtr->mechanism = CKM_MD5;
 	break;
     case NSSAlgorithmType_SHA1:
 	mechPtr->mechanism = CKM_SHA_1;
@@ -426,52 +782,59 @@ set_cryptoki_mechanism
     case NSSAlgorithmType_MAC:
     case NSSAlgorithmType_HMAC:
     default:
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
+/*
+ * convert a keypair type and keypair-specific parameters to a
+ * CK_MECHANISM.
+ */
 static PRStatus
-set_cryptoki_mechanism_for_keygen
+set_cryptoki_mechanism_for_keypair_gen
 (
   NSSAlgorithmAndParameters *ap,
-  NSSAlgorithmType algorithm,
+  NSSKeyPairType keyPairType,
   NSSParameters *parameters
 )
 {
     CK_MECHANISM_PTR mechPtr = &ap->mechanism;
-    switch (algorithm) {
-    case NSSAlgorithmType_RSA:
+    switch (keyPairType) {
+    case NSSKeyPairType_RSA:
 	mechPtr->mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
 	ap->params.rsakg = parameters->rsakg;
+	ap->set_template = rsa_keygen_settor;
 	break;
     case NSSAlgorithmType_DSA:
 	mechPtr->mechanism = CKM_DSA_KEY_PAIR_GEN;
 	ap->params.dsakg.primeBits = parameters->dsakg.primeBits;
 	if (parameters->dsakg.p.data != NULL) {
 	    nssItem_Duplicate(&parameters->dsakg.p, ap->arena,
 	                      &ap->params.dsakg.p);
 	    nssItem_Duplicate(&parameters->dsakg.q, ap->arena,
 	                      &ap->params.dsakg.q);
 	    nssItem_Duplicate(&parameters->dsakg.g, ap->arena,
 	                      &ap->params.dsakg.g);
 	}
+	ap->set_template = dsa_keygen_settor;
 	break;
     case NSSAlgorithmType_DH:
 	mechPtr->mechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
 	ap->params.dhkg.valueBits = parameters->dhkg.valueBits;
 	ap->params.dhkg.primeBits = parameters->dhkg.primeBits;
 	if (parameters->dhkg.p.data != NULL) {
 	    nssItem_Duplicate(&parameters->dhkg.p, ap->arena,
 	                      &ap->params.dhkg.p);
 	    nssItem_Duplicate(&parameters->dhkg.g, ap->arena,
 	                      &ap->params.dhkg.g);
 	}
+	ap->set_template = dh_keygen_settor;
 	break;
     case NSSAlgorithmType_DES:
 	mechPtr->mechanism = CKM_DES_KEY_GEN;
 	break;
     case NSSAlgorithmType_3DES:
 	mechPtr->mechanism = CKM_DES3_KEY_GEN;
 	break;
     case NSSAlgorithmType_AES:
@@ -491,168 +854,248 @@ set_cryptoki_mechanism_for_keygen
     case NSSAlgorithmType_HMAC:
     default:
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
 static PRStatus
-copy_algparam
+set_cryptoki_mechanism_for_symkey_gen
 (
-  NSSAlgorithmAndParameters *copy,
-  const NSSAlgorithmAndParameters *orig
+  NSSAlgorithmAndParameters *ap,
+  NSSSymmetricKeyType symKeyType,
+  NSSParameters *parameters
 )
 {
-    copy->algorithm = orig->algorithm;
-    copy->isKeyGen = orig->isKeyGen;
-    copy->mechanism.mechanism = orig->mechanism.mechanism;
-    copy->mechanism.pParameter = nss_ZAlloc(copy->arena,
-                                            orig->mechanism.ulParameterLen);
-    if (!copy->mechanism.pParameter) {
+    CK_MECHANISM_PTR mechPtr = &ap->mechanism;
+    switch (symKeyType) {
+    case NSSSymmetricKeyType_SSLPMS:
+	return set_sslpms_mechanism(mechPtr, parameters, ap->arena);
+    case NSSSymmetricKeyType_SSLMS:
+	return set_sslms_mechanism(mechPtr, parameters, ap->arena);
+    default:
+	/* XXX invalid args */
 	return PR_FAILURE;
     }
-    nsslibc_memcpy(copy->mechanism.pParameter,
-                   orig->mechanism.pParameter,
-                   orig->mechanism.ulParameterLen);
-    copy->mechanism.ulParameterLen = orig->mechanism.ulParameterLen;
-    if (orig->isKeyGen) {
-	set_cryptoki_mechanism_for_keygen(copy, orig->algorithm, 
-	                                  (NSSParameters *)&orig->params);
-    }
-    return PR_SUCCESS;
 }
 
-NSS_IMPLEMENT NSSAlgorithmAndParameters *
+static NSSAlgorithmAndParameters *
 create_algparam
 (
   NSSArena *arenaOpt,
-  NSSAlgorithmType algorithm,
-  NSSParameters *parametersOpt,
-  PRBool forKeyGen,
-  const NSSAlgorithmAndParameters *originalOpt
+  nssArenaMark **mark
 )
 {
-    PRStatus status;
     NSSArena *arena;
-    nssArenaMark *mark = NULL;
     NSSAlgorithmAndParameters *rvAP = NULL;
     if (arenaOpt) {
 	arena = arenaOpt;
-	mark = nssArena_Mark(arena);
-	if (!mark) {
+	*mark = nssArena_Mark(arena);
+	if (!*mark) {
 	    return (NSSAlgorithmAndParameters *)NULL;
 	}
     } else {
 	arena = nssArena_Create();
 	if (!arena) {
 	    return (NSSAlgorithmAndParameters *)NULL;
 	}
     }
     rvAP = nss_ZNEW(arena, NSSAlgorithmAndParameters);
     if (!rvAP) {
-	goto loser;
-    }
-    rvAP->algorithm = algorithm;
-    if (forKeyGen) {
-	status = set_cryptoki_mechanism_for_keygen(rvAP,
-	                                           algorithm, parametersOpt);
-	rvAP->isKeyGen = PR_TRUE;
-    } else if (!originalOpt) {
-	status = set_cryptoki_mechanism(&rvAP->mechanism, 
-	                                algorithm, parametersOpt, arena);
-	rvAP->isKeyGen = PR_FALSE;
-    } else {
-	status = copy_algparam(rvAP, originalOpt);
+	if (*mark) {
+	    nssArena_Release(arena, *mark);
+	} else {
+	    nssArena_Destroy(arena);
+	}
+	return (NSSAlgorithmAndParameters *)NULL;
     }
-    if (status != PR_SUCCESS) {
-	goto loser;
-    }
-    if (mark) {
-	nssArena_Unmark(arena, mark);
+    rvAP->arena = arena;
+    rvAP->set_template = null_settor; /* by default */
+    return rvAP;
+}
+
+static NSSAlgorithmAndParameters *
+finish_create_algparam
+(
+  NSSAlgorithmAndParameters *ap,
+  NSSArena *arena,
+  nssArenaMark *mark,
+  PRStatus isOK
+)
+{
+    if (isOK == PR_SUCCESS) {
+	if (mark) {
+	    nssArena_Unmark(arena, mark);
+	}
     } else {
-	rvAP->arena = arena;
+	if (mark) {
+	    nssArena_Release(arena, mark);
+	} else {
+	    nssArena_Destroy(arena);
+	}
+	ap = (NSSAlgorithmAndParameters *)NULL;
     }
-    return rvAP;
-loser:
-    if (mark) {
-	nssArena_Release(arena, mark);
-    } else {
-	nssArena_Destroy(arena);
-    }
-    return (NSSAlgorithmAndParameters *)NULL;
+    return ap;
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
 nssAlgorithmAndParameters_Create
 (
   NSSArena *arenaOpt,
   NSSAlgorithmType algorithm,
   NSSParameters *parametersOpt
 )
 {
-    return create_algparam(arenaOpt, algorithm, parametersOpt, 
-                           PR_FALSE, NULL);
+    PRStatus status;
+    nssArenaMark *mark = NULL;
+    NSSAlgorithmAndParameters *rvAP = NULL;
+
+    rvAP = create_algparam(arenaOpt, &mark);
+    if (!rvAP) {
+	return (NSSAlgorithmAndParameters *)NULL;
+    }
+
+    status = set_cryptoki_mechanism(&rvAP->mechanism, 
+                                    algorithm, parametersOpt, rvAP->arena);
+
+    return finish_create_algparam(rvAP, rvAP->arena, mark, status);
+}
+
+NSS_IMPLEMENT NSSAlgorithmAndParameters *
+nssAlgorithmAndParameters_CreateKeyPairGen
+(
+  NSSArena *arenaOpt,
+  NSSKeyPairType keyPairType,
+  NSSParameters *parametersOpt
+)
+{
+    PRStatus status;
+    nssArenaMark *mark = NULL;
+    NSSAlgorithmAndParameters *rvAP = NULL;
+
+    rvAP = create_algparam(arenaOpt, &mark);
+    if (!rvAP) {
+	return (NSSAlgorithmAndParameters *)NULL;
+    }
+
+    status = set_cryptoki_mechanism_for_keypair_gen(rvAP, 
+                                                    keyPairType, 
+                                                    parametersOpt);
+
+    return finish_create_algparam(rvAP, rvAP->arena, mark, status);
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
-nssAlgorithmAndParameters_CreateKeyGen
+nssAlgorithmAndParameters_CreateSSLSessionKeyDerivation
 (
   NSSArena *arenaOpt,
-  NSSAlgorithmType algorithm,
-  NSSParameters *parametersOpt
+  NSSSSLSessionParameters *parameters
 )
 {
-    return create_algparam(arenaOpt, algorithm, parametersOpt, 
-                           PR_TRUE, NULL);
+    PRStatus status;
+    nssArenaMark *mark = NULL;
+    NSSAlgorithmAndParameters *rvAP = NULL;
+
+    rvAP = create_algparam(arenaOpt, &mark);
+    if (!rvAP) {
+	return (NSSAlgorithmAndParameters *)NULL;
+    }
+
+    status = set_sslsession_derive_mechanism(&rvAP->mechanism,
+                                             parameters,
+                                             rvAP->arena);
+
+    return finish_create_algparam(rvAP, rvAP->arena, mark, status);
+}
+
+/* this is how it was done in 3.X, but something not involving a
+ * huge switch would be nicer
+ */
+static PRStatus
+decode_params(NSSAlgorithmAndParameters *ap, const NSSItem *params)
+{
+    /* Algorithms that only take an IV parameter */
+    switch (ap->mechanism.mechanism) {
+    case CKM_AES_CBC:
+    case CKM_AES_CBC_PAD:
+    case CKM_DES_CBC:
+    case CKM_DES_CBC_PAD:
+    case CKM_DES3_CBC:
+    case CKM_DES3_CBC_PAD:
+    case CKM_IDEA_CBC:
+    case CKM_IDEA_CBC_PAD:
+    case CKM_CDMF_CBC:
+    case CKM_CDMF_CBC_PAD:
+    case CKM_CAST_CBC:
+    case CKM_CAST_CBC_PAD:
+    case CKM_CAST3_CBC:
+    case CKM_CAST3_CBC_PAD:
+    case CKM_CAST5_CBC:
+    case CKM_CAST5_CBC_PAD:
+    case CKM_SKIPJACK_CFB8:
+    case CKM_SKIPJACK_CFB16:
+    case CKM_SKIPJACK_CFB32:
+    case CKM_SKIPJACK_ECB64:
+    case CKM_SKIPJACK_CBC64:
+    case CKM_SKIPJACK_OFB64:
+    case CKM_SKIPJACK_CFB64:
+    case CKM_BATON_ECB96:
+    case CKM_BATON_ECB128:
+    case CKM_BATON_CBC128:
+    case CKM_BATON_COUNTER:
+    case CKM_BATON_SHUFFLE:
+    case CKM_JUNIPER_ECB128:
+    case CKM_JUNIPER_CBC128:
+    case CKM_JUNIPER_COUNTER:
+    case CKM_JUNIPER_SHUFFLE:  
+	return decode_iv(ap, params);
+    default: /* keep going */
+	break;
+    }
+
+    /* Algorithms that take more complicated parameters */
+    switch (ap->mechanism.mechanism) {
+    case CKM_RC2_ECB:          return decode_rc2_ecb(ap, params);
+    case CKM_RC2_CBC:
+    case CKM_RC2_CBC_PAD:      return decode_rc2_cbc(ap, params);
+    default:
+	/* XXX unsupported alg or something */
+	return PR_FAILURE;
+    }
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
 nssAlgorithmAndParameters_CreateFromOID
 (
   NSSArena *arenaOpt,
   CK_MECHANISM_TYPE algorithm,
   const NSSItem *parametersOpt
 )
 {
+    PRStatus status;
     NSSArena *arena;
     nssArenaMark *mark = NULL;
     NSSAlgorithmAndParameters *rvAP = NULL;
 
-    if (arenaOpt) {
-	arena = arenaOpt;
-	mark = nssArena_Mark(arena);
-	if (!mark) {
-	    return (NSSAlgorithmAndParameters *)NULL;
-	}
-    } else {
-	arena = nssArena_Create();
-	if (!arena) {
-	    return (NSSAlgorithmAndParameters *)NULL;
-	}
-    }
-    rvAP = nss_ZNEW(arena, NSSAlgorithmAndParameters);
+    rvAP = create_algparam(arenaOpt, &mark);
     if (!rvAP) {
-	goto loser;
+	return (NSSAlgorithmAndParameters *)NULL;
     }
+
     rvAP->mechanism.mechanism = algorithm;
-    /* XXX */
-    if (mark) {
-	nssArena_Unmark(arena, mark);
+
+    if (parametersOpt) {
+	status = decode_params(rvAP, parametersOpt);
     } else {
-	rvAP->arena = arena;
+	/* XXX not catching algorithms that require parameters here */
+	status = PR_SUCCESS;
     }
-    return rvAP;
-loser:
-    if (mark) {
-	nssArena_Release(arena, mark);
-    } else {
-	nssArena_Destroy(arena);
-    }
-    return (NSSAlgorithmAndParameters *)NULL;
+
+    return finish_create_algparam(rvAP, arena, mark, status);
 }
 
 NSS_IMPLEMENT void
 nssAlgorithmAndParameters_Destroy
 (
   NSSAlgorithmAndParameters *ap
 )
 {
@@ -678,118 +1121,93 @@ nssAlgorithmAndParameters_GetMechanism2
   const NSSAlgorithmAndParameters *ap,
   CK_MECHANISM_PTR pMechanism
 )
 {
     *pMechanism = ap->mechanism;
 }
 #endif
 
-/* returns the number of template values set */
-NSS_IMPLEMENT PRUint32
+NSS_IMPLEMENT PRIntn
 nssAlgorithmAndParameters_SetTemplateValues
 (
   const NSSAlgorithmAndParameters *ap,
   CK_ATTRIBUTE_PTR aTemplate,
   CK_ULONG templateSize
 )
 {
-    CK_ATTRIBUTE_PTR attr = aTemplate;
-    switch(ap->algorithm) {
-    case NSSAlgorithmType_RSA: 
-	if (ap->isKeyGen) {
-	    PRUint32 tmp;
-	    /* set the modulus bits parameter in the template */
-	    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_MODULUS_BITS,
-	                             ap->params.rsakg.modulusBits);
-	    /* set the public exponent parameter in the template */
-	    tmp = PR_htonl(ap->params.rsakg.publicExponent);
-	    nsslibc_memcpy((void *)ap->rsape, &tmp, sizeof(tmp));
-	    attr->type = CKA_PUBLIC_EXPONENT; 
-	    attr->pValue = (CK_BYTE_PTR)ap->rsape;
-	    attr->ulValueLen = sizeof(ap->rsape);
-	    attr++;
-	}
-	break;
-    case NSSAlgorithmType_DSA:
-	if (ap->isKeyGen) {
-	    if (ap->params.dsakg.p.data == NULL) {
-		/* XXX ? */
-		PR_ASSERT(0);
-	    } else {
-		/* P */
-		NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_PRIME,
-		                          &ap->params.dsakg.p);
-		/* Q */
-		NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBPRIME,
-		                          &ap->params.dsakg.q);
-		/* G */
-		NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_BASE,
-		                          &ap->params.dsakg.g);
-	    }
-	}
-	break;
-    case NSSAlgorithmType_DH:
-	if (ap->isKeyGen) {
-	    if (ap->params.dhkg.p.data == NULL) {
-		/* XXX ? */
-		PR_ASSERT(0);
-	    } else {
-		/* P */
-		NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_PRIME,
-		                          &ap->params.dhkg.p);
-		/* G */
-		NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_BASE,
-		                          &ap->params.dhkg.g);
-		/* constraint on private value */
-		NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_VALUE_BITS,
-		                         ap->params.dhkg.valueBits);
-	    }
-	}
-	break;
-    default:
-	break;
+    return ap->set_template(ap, aTemplate, templateSize);
+}
+
+static PRStatus
+copy_algparam
+(
+  NSSAlgorithmAndParameters *copy,
+  const NSSAlgorithmAndParameters *orig
+)
+{
+    copy->mechanism.mechanism = orig->mechanism.mechanism;
+    copy->mechanism.pParameter = nss_ZAlloc(copy->arena,
+                                            orig->mechanism.ulParameterLen);
+    if (!copy->mechanism.pParameter) {
+	return PR_FAILURE;
     }
-    return attr - aTemplate;
+    nsslibc_memcpy(copy->mechanism.pParameter,
+                   orig->mechanism.pParameter,
+                   orig->mechanism.ulParameterLen);
+    copy->mechanism.ulParameterLen = orig->mechanism.ulParameterLen;
+    return PR_SUCCESS;
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
 nssAlgorithmAndParameters_Clone
 (
   const NSSAlgorithmAndParameters *ap,
   NSSArena *arenaOpt
 )
 {
-    return create_algparam(arenaOpt, ap->algorithm, NULL, PR_FALSE, ap);
+    PRStatus status;
+    NSSArena *arena;
+    nssArenaMark *mark = NULL;
+    NSSAlgorithmAndParameters *rvAP = NULL;
+
+    rvAP = create_algparam(arenaOpt, &mark);
+    if (!rvAP) {
+	return (NSSAlgorithmAndParameters *)NULL;
+    }
+
+    status = copy_algparam(rvAP, ap);
+
+    return finish_create_algparam(rvAP, arena, mark, status);
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
 NSSAlgorithmAndParameters_Create
 (
   NSSArena *arenaOpt,
   NSSAlgorithmType algorithm,
   NSSParameters *parametersOpt
 )
 {
     return nssAlgorithmAndParameters_Create(arenaOpt, 
                                             algorithm, 
                                             parametersOpt);
 }
 
 NSS_IMPLEMENT NSSAlgorithmAndParameters *
-NSSAlgorithmAndParameters_CreateKeyGen
+NSSAlgorithmAndParameters_CreateKeyPairGen
 (
   NSSArena *arenaOpt,
-  NSSAlgorithmType algorithm,
+  NSSKeyPairType keyPairType,
   NSSParameters *parametersOpt
 )
 {
-    return nssAlgorithmAndParameters_CreateKeyGen(arenaOpt, 
-                                                  algorithm, 
-                                                  parametersOpt);
+    return nssAlgorithmAndParameters_CreateKeyPairGen(arenaOpt, 
+                                                      keyPairType, 
+                                                      parametersOpt);
 }
 
 NSS_IMPLEMENT void
 NSSAlgorithmAndParameters_Destroy
 (
   NSSAlgorithmAndParameters *ap
 )
 {
--- a/security/nss/lib/dev/ckhelper.c
+++ b/security/nss/lib/dev/ckhelper.c
@@ -924,8 +924,22 @@ nssCryptokiSymmetricKey_Copy
 
     nssArena_Destroy(arena);
     return key;
 loser:
     nssArena_Destroy(arena);
     return (nssCryptokiObject *)NULL;
 }
 
+NSS_IMPLEMENT void
+nss_SetGenericDeviceError (
+  CK_RV ckrv
+)
+{
+    NSSError e;
+    switch (ckrv) {
+    case CKR_DEVICE_REMOVED: e = NSS_ERROR_DEVICE_REMOVED; break;
+    case CKR_HOST_MEMORY:
+    case CKR_DEVICE_MEMORY:  e = NSS_ERROR_NO_MEMORY;      break;
+    default:                 e = NSS_ERROR_DEVICE_ERROR;   break;
+    }
+    nss_SetError(e);
+}
--- a/security/nss/lib/dev/dev.h
+++ b/security/nss/lib/dev/dev.h
@@ -753,16 +753,49 @@ nssToken_DeriveKey
   nssSession *session,
   const NSSAlgorithmAndParameters *ap,
   nssCryptokiObject *baseKey,
   PRBool asTokenObject,
   NSSOperations operations,
   NSSProperties properties
 );
 
+/*
+ *
+ * rvSessionKeys -- [0] client MAC
+ *                  [1] server MAC
+ *                  [2] client write
+ *                  [3] server write
+ */
+NSS_EXTERN PRStatus
+nssToken_DeriveSSLSessionKeys
+(
+  NSSToken *token,
+  nssSession *session,
+  const NSSAlgorithmAndParameters *ap,
+  nssCryptokiObject *masterSecret,
+  NSSOperations operations,
+  NSSProperties properties,
+  nssCryptokiObject **rvSessionKeys /* [4] */
+);
+
+NSS_EXTERN PRStatus
+nssToken_SeedRandom (
+  NSSToken *token,
+  NSSItem *seed
+);
+
+NSS_EXTERN PRUint8 *
+nssToken_GenerateRandom (
+  NSSToken *token,
+  PRUint8 *rvOpt,
+  PRUint32 numBytes,
+  NSSArena *arenaOpt
+);
+
 NSS_EXTERN NSSItem *
 nssToken_Encrypt
 (
   NSSToken *tok,
   nssSession *session,
   const NSSAlgorithmAndParameters *ap,
   nssCryptokiObject *key,
   NSSItem *data,
@@ -981,16 +1014,23 @@ NSS_EXTERN NSSAlgorithmAndParameters *
 nssAlgorithmAndParameters_CreateFromOID
 (
   NSSArena *arenaOpt,
   CK_MECHANISM_TYPE algorithm,
   const NSSItem *parametersOpt
 );
 
 NSS_EXTERN NSSAlgorithmAndParameters *
+nssAlgorithmAndParameters_CreateSSLSessionKeyDerivation
+(
+  NSSArena *arenaOpt,
+  NSSSSLSessionParameters *parameters
+);
+
+NSS_EXTERN NSSAlgorithmAndParameters *
 nssAlgorithmAndParameters_Clone
 (
   const NSSAlgorithmAndParameters *ap,
   NSSArena *arenaOpt
 );
 
 NSS_EXTERN void
 nssAlgorithmAndParameters_Destroy
--- a/security/nss/lib/dev/devm.h
+++ b/security/nss/lib/dev/devm.h
@@ -164,24 +164,29 @@ nssCryptokiObject_Create
 );
 
 NSS_EXTERN CK_MECHANISM_PTR
 nssAlgorithmAndParameters_GetMechanism
 (
   const NSSAlgorithmAndParameters *ap
 );
 
-NSS_EXTERN PRUint32
+NSS_EXTERN PRIntn
 nssAlgorithmAndParameters_SetTemplateValues
 (
   const NSSAlgorithmAndParameters *ap,
   CK_ATTRIBUTE_PTR aTemplate,
   CK_ULONG templateSize
 );
 
+NSS_EXTERN void
+nss_SetGenericDeviceError (
+  CK_RV ckrv
+);
+
 NSS_EXTERN nssTokenObjectCache *
 nssTokenObjectCache_Create
 (
   NSSToken *token,
   PRBool cacheCerts,
   PRBool cacheTrust,
   PRBool cacheCRLs
 );
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -1173,50 +1173,16 @@ nssToken_FindPublicKeyByID
 	    }
 	}
 #endif /* SOFTOKEN_RETURNS_PUBKEY_BUG */
 	nss_ZFreeIf(objects);
     }
     return rvKey;
 }
 
-static void
-sha1_hash(NSSItem *input, NSSItem *output)
-{
-#ifdef NSS_3_4_CODE
-    PK11SlotInfo *internal = PK11_GetInternalSlot();
-    NSSToken *token = PK11Slot_GetNSSToken(internal);
-#else
-    NSSToken *token = nss_GetDefaultCryptoToken();
-#endif
-    (void)nssToken_Digest(token, token->defaultSession,
-                          NSSAlgorithmAndParameters_SHA1,
-                          input, output, NULL);
-#ifdef NSS_3_4_CODE
-    PK11_FreeSlot(token->pk11slot);
-#endif
-}
-
-static void
-md5_hash(NSSItem *input, NSSItem *output)
-{
-#ifdef NSS_3_4_CODE
-    PK11SlotInfo *internal = PK11_GetInternalSlot();
-    NSSToken *token = PK11Slot_GetNSSToken(internal);
-#else
-    NSSToken *token = nss_GetDefaultCryptoToken();
-#endif
-    (void)nssToken_Digest(token, token->defaultSession,
-                          NSSAlgorithmAndParameters_MD5,
-                          input, output, NULL);
-#ifdef NSS_3_4_CODE
-    PK11_FreeSlot(token->pk11slot);
-#endif
-}
-
 static CK_TRUST
 get_ck_trust
 (
   nssTrustLevel nssTrust
 )
 {
     CK_TRUST t;
     switch (nssTrust) {
@@ -1247,38 +1213,29 @@ nssToken_ImportTrust
 )
 {
     nssCryptokiObject *object;
     CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
     CK_TRUST ckSA, ckCA, ckCS, ckEP;
     CK_ATTRIBUTE_PTR attr;
     CK_ATTRIBUTE trust_tmpl[10];
     CK_ULONG tsize;
-    PRUint8 sha1[20]; /* this is cheating... */
-    PRUint8 md5[16];
-    NSSItem sha1_result, md5_result;
-    sha1_result.data = sha1; sha1_result.size = sizeof sha1;
-    md5_result.data = md5; md5_result.size = sizeof md5;
-    sha1_hash(certEncoding, &sha1_result);
-    md5_hash(certEncoding, &md5_result);
     ckSA = get_ck_trust(serverAuth);
     ckCA = get_ck_trust(clientAuth);
     ckCS = get_ck_trust(codeSigning);
     ckEP = get_ck_trust(emailProtection);
     NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize);
     if (asTokenObject) {
 	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
     } else {
 	NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
     }
     NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS,           tobjc);
     NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER,          certIssuer);
     NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER,   certSerial);
-    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result);
-    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH,  &md5_result);
     /* now set the trust values */
     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH,      ckSA);
     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH,      ckCA);
     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING,     ckCS);
     NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP);
     NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize);
     /* import the trust object onto the token */
     object = import_object(tok, session, trust_tmpl, tsize);
@@ -1476,16 +1433,74 @@ nssToken_FindCRLsBySubject
     NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
 
     objects = find_objects_by_template(token, session,
                                        crlobj_template, crlobj_size,
                                        maximumOpt, statusOpt);
     return objects;
 }
 
+NSS_IMPLEMENT PRStatus
+nssToken_SeedRandom (
+  NSSToken *token,
+  NSSItem *seed
+)
+{
+    CK_RV ckrv;
+    void *epv = nssToken_GetCryptokiEPV(token);
+    nssSession *session = token->defaultSession;
+
+    nssSession_EnterMonitor(session);
+    ckrv = CKAPI(epv)->C_SeedRandom(session->handle, seed->data, seed->size);
+    nssSession_ExitMonitor(session);
+    if (ckrv != CKR_OK) {
+	if (ckrv == CKR_RANDOM_SEED_NOT_SUPPORTED ||
+	    ckrv == CKR_RANDOM_NO_RNG) 
+	{
+	    nss_SetError(NSS_ERROR_INVALID_DEVICE);
+	} else {
+	    nss_SetGenericDeviceError(ckrv);
+	}
+	return PR_FAILURE;
+    }
+    return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRUint8 *
+nssToken_GenerateRandom (
+  NSSToken *token,
+  PRUint8 *rvOpt,
+  PRUint32 numBytes,
+  NSSArena *arenaOpt
+)
+{
+    CK_RV ckrv;
+    void *epv = nssToken_GetCryptokiEPV(token);
+    nssSession *session = token->defaultSession;
+
+    if (!rvOpt) {
+	rvOpt = nss_ZAlloc(arenaOpt, numBytes);
+	if (!rvOpt) {
+	    return (PRUint8 *)NULL;
+	}
+    }
+    nssSession_EnterMonitor(session);
+    ckrv = CKAPI(epv)->C_GenerateRandom(session->handle, rvOpt, numBytes);
+    nssSession_ExitMonitor(session);
+    if (ckrv != CKR_OK) {
+	if (ckrv == CKR_RANDOM_NO_RNG) {
+	    nss_SetError(NSS_ERROR_INVALID_DEVICE);
+	} else {
+	    nss_SetGenericDeviceError(ckrv);
+	}
+	return (PRUint8 *)NULL;
+    }
+    return rvOpt;
+}
+
 #define PUBLIC_KEY_PROPS_MASK \
     (NSSProperties_PRIVATE | NSSProperties_READ_ONLY)
 
 #define PUBLIC_KEY_OPS_MASK \
     (NSSOperations_DERIVE | NSSOperations_ENCRYPT        | \
      NSSOperations_VERIFY | NSSOperations_VERIFY_RECOVER | \
      NSSOperations_WRAP)
 
@@ -1862,16 +1877,97 @@ nssToken_DeriveKey
                                    keyTemplate, ktSize, &keyH);
     nssSession_ExitMonitor(session);
     if (ckrv == CKR_OK) {
 	derivedKey = nssCryptokiObject_Create(token, session, keyH);
     }
     return derivedKey;
 }
 
+NSS_IMPLEMENT PRStatus
+nssToken_DeriveSSLSessionKeys
+(
+  NSSToken *token,
+  nssSession *session,
+  const NSSAlgorithmAndParameters *ap,
+  nssCryptokiObject *masterSecret,
+  NSSOperations operations,
+  NSSProperties properties,
+  nssCryptokiObject **rvSessionKeys /* [4] */
+)
+{
+    CK_RV ckrv;
+    CK_MECHANISM_PTR mechanism;
+    CK_OBJECT_HANDLE keyH;
+    CK_ATTRIBUTE keyTemplate[14];
+    CK_ATTRIBUTE_PTR attr = keyTemplate;
+    CK_ULONG ktSize;
+    void *epv = nssToken_GetCryptokiEPV(token);
+
+    mechanism = nssAlgorithmAndParameters_GetMechanism(ap);
+
+    /* set up the key template */
+    NSS_CK_TEMPLATE_START(keyTemplate, attr, ktSize);
+    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
+    if (operations) {
+	attr += nssCKTemplate_SetOperationAttributes(attr, 
+	                                             keyTemplate - attr,
+	                                             operations);
+    }
+
+    if (properties) {
+	attr += nssCKTemplate_SetPropertyAttributes(attr,
+	                                            keyTemplate - attr,
+                                                    properties);
+    }
+    NSS_CK_TEMPLATE_FINISH(keyTemplate, attr, ktSize);
+    /* ready to do the derivation */
+    nssSession_EnterMonitor(session);
+    ckrv = CKAPI(epv)->C_DeriveKey(session->handle, mechanism,
+                                   masterSecret->handle,
+                                   keyTemplate, ktSize, &keyH);
+    nssSession_ExitMonitor(session);
+    if (ckrv == CKR_OK) {
+	CK_SSL3_KEY_MAT_PARAMS *kmp;
+	CK_SSL3_KEY_MAT_OUT_PTR kmo;
+
+	kmp = (CK_SSL3_KEY_MAT_PARAMS *)mechanism->pParameter;
+	kmo = kmp->pReturnedKeyMaterial;
+	/* XXX all in the same session? */
+	rvSessionKeys[0] = nssCryptokiObject_Create(token, session, 
+	                                            kmo->hClientMacSecret);
+	if (!rvSessionKeys[0]) {
+	    return PR_FAILURE;
+	}
+	rvSessionKeys[1] = nssCryptokiObject_Create(token, session, 
+	                                            kmo->hServerMacSecret);
+	if (!rvSessionKeys[1]) {
+	    nssCryptokiObject_Destroy(rvSessionKeys[0]);
+	    return PR_FAILURE;
+	}
+	rvSessionKeys[2] = nssCryptokiObject_Create(token, session, 
+	                                            kmo->hClientKey);
+	if (!rvSessionKeys[2]) {
+	    nssCryptokiObject_Destroy(rvSessionKeys[0]);
+	    nssCryptokiObject_Destroy(rvSessionKeys[1]);
+	    return PR_FAILURE;
+	}
+	rvSessionKeys[3] = nssCryptokiObject_Create(token, session, 
+	                                            kmo->hServerKey);
+	if (!rvSessionKeys[3]) {
+	    nssCryptokiObject_Destroy(rvSessionKeys[0]);
+	    nssCryptokiObject_Destroy(rvSessionKeys[1]);
+	    nssCryptokiObject_Destroy(rvSessionKeys[2]);
+	    return PR_FAILURE;
+	}
+	return PR_SUCCESS;
+    }
+    return PR_FAILURE;
+}
+
 NSS_IMPLEMENT NSSItem *
 nssToken_Encrypt
 (
   NSSToken *tok,
   nssSession *session,
   const NSSAlgorithmAndParameters *ap,
   nssCryptokiObject *key,
   NSSItem *data,
@@ -2475,17 +2571,17 @@ nssToken_Verify
 	    /* the verification failed */
 	    nss_SetError(NSS_ERROR_INVALID_SIGNATURE);
 	} else if (ckrv == CKR_SIGNATURE_LEN_RANGE) {
 	    /* signature->len is invalid, which is more like bad input
 	     * than an invalid signature
 	     */
 	    nss_SetError(NSS_ERROR_INVALID_DATA);
 	} else {
-	    nss_SetError(NSS_ERROR_TOKEN_FAILURE);
+	    nss_SetGenericDeviceError(ckrv);
 	}
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
 NSS_IMPLEMENT PRStatus
 nssToken_BeginVerify
@@ -2547,17 +2643,17 @@ nssToken_FinishVerify
 	    /* the verification failed */
 	    nss_SetError(NSS_ERROR_INVALID_SIGNATURE);
 	} else if (ckrv == CKR_SIGNATURE_LEN_RANGE) {
 	    /* signature->len is invalid, which is more like bad input
 	     * than an invalid signature
 	     */
 	    nss_SetError(NSS_ERROR_INVALID_DATA);
 	} else {
-	    nss_SetError(NSS_ERROR_TOKEN_FAILURE);
+	    nss_SetGenericDeviceError(ckrv);
 	}
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
 NSS_IMPLEMENT NSSItem *
 nssToken_VerifyRecover
--- a/security/nss/lib/dev/nssdev.h
+++ b/security/nss/lib/dev/nssdev.h
@@ -203,20 +203,28 @@ NSS_EXTERN NSSAlgorithmAndParameters *
 NSSAlgorithmAndParameters_Create
 (
   NSSArena *arenaOpt,
   NSSAlgorithmType algorithm,
   NSSParameters *parameters
 );
 
 NSS_EXTERN NSSAlgorithmAndParameters *
-NSSAlgorithmAndParameters_CreateKeyGen
+NSSAlgorithmAndParameters_CreateKeyPairGen
 (
   NSSArena *arenaOpt,
-  NSSAlgorithmType algorithm,
+  NSSKeyPairType keyPairType,
+  NSSParameters *parametersOpt
+);
+
+NSS_EXTERN NSSAlgorithmAndParameters *
+NSSAlgorithmAndParameters_CreateSymKeyGen
+(
+  NSSArena *arenaOpt,
+  NSSSymmetricKeyType symKeyType,
   NSSParameters *parametersOpt
 );
 
 NSS_EXTERN NSSAlgorithmAndParameters *
 NSSAlgorithmAndParameters_CreateMAC
 (
   NSSArena *arenaOpt,
   NSSAlgorithmType blockCipher,
--- a/security/nss/lib/dev/nssdevt.h
+++ b/security/nss/lib/dev/nssdevt.h
@@ -60,16 +60,350 @@ typedef struct NSSTokenStr NSSToken;
  * NSSAlgorithmAndParameters
  *
  * Algorithm is an OID
  * Parameters depend on the algorithm
  */
 
 typedef struct NSSAlgorithmAndParametersStr NSSAlgorithmAndParameters;
 
+/*
+ * NSSCallback
+ *
+ * At minimum, a "challenge" method and a closure argument.
+ * Usually the challenge will just be prompting for a password.
+ * How OO do we want to make it?
+ */
+
+typedef struct NSSCallbackStr NSSCallback;
+
+struct NSSCallbackStr {
+    /* Prompt for a password to initialize a slot.  */
+    PRStatus (* getInitPW)(NSSUTF8 *slotName, void *arg, NSSUTF8 **password); 
+    /* Prompt for slot password.  */
+    PRStatus (* getPW)(NSSUTF8 *slotName, PRBool *retry, void *arg,
+                       NSSUTF8 **password); 
+    void *arg;
+};
+
+typedef enum {
+  NSSCertificateType_Unknown = 0,
+  NSSCertificateType_PKIX = 1
+} NSSCertificateType;
+
+typedef enum
+{
+  NSSKeyPairType_Unknown = 0,
+  NSSKeyPairType_RSA = 1,
+  NSSKeyPairType_DSA = 2,
+  NSSKeyPairType_DiffieHellman = 3
+} NSSKeyPairType;
+
+typedef struct NSSRSAPublicKeyInfoStr
+{
+  NSSItem modulus;
+  NSSItem publicExponent;
+}
+NSSRSAPublicKeyInfo;
+
+typedef struct NSSDSAPublicKeyInfoStr
+{
+#if 0
+  NSSPQGParameters params;
+#endif
+  NSSItem publicValue;
+}
+NSSDSAPublicKeyInfo;
+
+typedef struct NSSDHPublicKeyInfoStr
+{
+  NSSItem prime;
+  NSSItem base;
+  NSSItem publicValue;
+}
+NSSDHPublicKeyInfo;
+
+typedef struct NSSPublicKeyInfoStr
+{
+  NSSKeyPairType kind;
+  union {
+    NSSRSAPublicKeyInfo rsa;
+    NSSDSAPublicKeyInfo dsa;
+    NSSDHPublicKeyInfo  dh;
+  } u;
+}
+NSSPublicKeyInfo;
+
+typedef enum
+{
+  NSSSymmetricKeyType_Unknown = 0,
+  NSSSymmetricKeyType_DES = 1,
+  NSSSymmetricKeyType_TripleDES = 2,
+  NSSSymmetricKeyType_RC2 = 3,
+  NSSSymmetricKeyType_RC4 = 4,
+  NSSSymmetricKeyType_RC5 = 5,
+  NSSSymmetricKeyType_AES = 6,
+  NSSSymmetricKeyType_SSLPMS = 7,
+  NSSSymmetricKeyType_SSLMS = 8
+} NSSSymmetricKeyType;
+
+/* set errors - user cancelled, ... */
+
+typedef enum {
+  NSSAlgorithmType_NULL   =  0,
+  NSSAlgorithmType_RSA    =  1,
+  NSSAlgorithmType_DSA    =  2,
+  NSSAlgorithmType_DH     =  3,
+  NSSAlgorithmType_DES    =  4,
+  NSSAlgorithmType_3DES   =  5,
+  NSSAlgorithmType_AES    =  6,
+  NSSAlgorithmType_RC2    =  7,
+  NSSAlgorithmType_RC4    =  8,
+  NSSAlgorithmType_RC5    =  9,
+  NSSAlgorithmType_MD2    = 10,
+  NSSAlgorithmType_MD5    = 11,
+  NSSAlgorithmType_SHA1   = 12,
+  NSSAlgorithmType_PBE    = 13,
+  NSSAlgorithmType_MAC    = 14,
+  NSSAlgorithmType_HMAC   = 15,
+} NSSAlgorithmType;
+
+/*
+ * RSA
+ */
+
+/* key generation */
+typedef struct NSSRSAKeyGenParametersStr
+{
+  PRUint32 modulusBits;
+  PRUint32 publicExponent;
+}
+NSSRSAKeyGenParameters;
+
+/*
+ * cipher operations
+ * DEFAULT: RAW (X.509)
+ */
+typedef enum {
+  NSSRSABlockFormat_Raw              = 0,
+  NSSRSABlockFormat_PKCS1            = 1,
+  NSSRSABlockFormat_PKCS1_WITH_MD2   = 2,
+  NSSRSABlockFormat_PKCS1_WITH_MD5   = 3,
+  NSSRSABlockFormat_PKCS1_WITH_SHA1  = 4,
+  NSSRSABlockFormat_PKCS1_OAEP       = 5
+} NSSRSABlockFormat;
+
+typedef NSSRSABlockFormat NSSRSAParameters;
+
+/*
+ * DSA
+ */
+
+/* key generation */
+typedef struct NSSDSAKeyGenParametersStr
+{
+  PRUint32 primeBits;
+  NSSItem p, q, g;          /* set of PQG parameters (can be zero)    */
+}
+NSSDSAKeyGenParameters;
+
+/*
+ * signature/verification
+ * DEFAULT: "raw" (no hashing)
+ */
+typedef NSSAlgorithmType NSSDSAParameters; /* hash algorithm */
+
+/*
+ * Diffie-Hellman
+ */
+
+/*
+ * key generation
+ *
+ * Note: the size of p and g in Diffie-Hellman is not bounded above.
+ * The parameters must use an unconstrained datum to represent p and g.
+ * The memory used for p and g below is within the scope of the caller,
+ * any NSS function will copy as necessary.
+ */
+typedef struct NSSDHParametersStr 
+{
+  PRUint32 valueBits;
+  PRUint32 primeBits;
+  NSSItem p, g; /* P and G values (can be zero) */
+}
+NSSDHKeyGenParameters;
+
+/*
+ * DES and Triple-DES
+ */
+
+/* 
+ * encryption/decryption parameters 
+ * DEFAULT: ECB mode
+ */
+typedef struct NSSDESParametersStr
+{
+  PRBool pkcsPad;
+  NSSItem iv;
+}
+NSSDESParameters;
+
+/*
+ * AES
+ */
+
+/* encryption/decryption parameters */
+typedef struct NSSAESParametersStr
+{
+#if 0
+  /* PKCS #11 is assuming 128-bit blocks */
+  PRUint32 blockSizeInBits;
+#endif
+  PRBool pkcsPad;
+  NSSItem iv;
+}
+NSSAESParameters;
+
+/*
+ * RC2
+ */
+
+/* encryption/decryption parameters */
+typedef struct NSSRC2ParametersStr
+{
+  PRUint32 effectiveKeySizeInBits;
+  PRBool pkcsPad;
+  NSSItem iv;
+}
+NSSRC2Parameters;
+
+/*
+ * RC4
+ */
+
+/*
+ * RC5
+ */
+
+/* encryption/decryption parameters */
+typedef struct NSSRC5ParametersStr
+{
+  PRUint32 wordSize;
+  PRUint32 numRounds;
+  PRBool pkcsPad;
+  NSSItem iv;
+}
+NSSRC5Parameters;
+
+/*
+ * HMAC
+ *
+ * DEFAULT: maximum length, specific to hash algorithm
+ */
+
+typedef PRUint32 NSSHMACParameters; /* length in bytes of desired output */
+
+/*
+ * Key derivation
+ */
+
+#if 0
+typedef struct NSSKeyDerivationParametersStr
+{
+}
+NSSKeyDerivationParameters;
+#endif
+
+/*
+ * PBE key generation
+ */
+
+/* NSS will always copy from this data */
+typedef struct NSSPBEKeyGenParametersStr
+{
+  NSSItem iv;
+  NSSUTF8 *password;
+  NSSItem salt;
+  PRUint32 iterations;
+}
+NSSPBEKeyGenParameters;
+
+/*
+ * SSL
+ */
+
+/* XXX */
+typedef enum {
+  NSSSSLVersion_SSLv2 = 0,
+  NSSSSLVersion_SSLv3 = 1,
+  NSSSSLVersion_TLS = 2
+} NSSSSLVersion;
+
+typedef NSSSSLVersion NSSSSLPreMasterSecretParameters;
+
+typedef struct NSSSSLMSParametersStr 
+{
+  NSSItem clientRandom;
+  NSSItem serverRandom;
+  NSSSSLVersion version;
+} 
+NSSSSLMasterSecretParameters;
+
+typedef struct NSSSSLSessionParametersStr
+{
+  PRUint32 macSizeInBits;
+  PRUint32 keySizeInBits;
+  PRUint32 ivSizeInBits;
+  PRBool isExport;
+  NSSItem clientRandom;
+  NSSItem serverRandom;
+  NSSSSLVersion version;
+} 
+NSSSSLSessionParameters;
+
+
+typedef union
+{
+  NSSRSAKeyGenParameters rsakg;
+  NSSDSAKeyGenParameters dsakg;
+  NSSDHKeyGenParameters  dhkg;
+  NSSPBEKeyGenParameters pbekg;
+  NSSRSAParameters       rsa;
+  NSSDSAParameters       dsa;
+  NSSDESParameters       des;
+  NSSAESParameters       aes;
+  NSSRC2Parameters       rc2;
+  NSSRC5Parameters       rc5;
+  NSSHMACParameters      hmac;
+  NSSSSLPreMasterSecretParameters sslpms;
+  NSSSSLMasterSecretParameters    sslms;
+}
+NSSParameters;
+
+typedef PRUint32 NSSOperations;
+/* 1) Do we want these to be preprocessor definitions or constants? */
+/* 2) What is the correct and complete list? */
+
+#define NSSOperations_ENCRYPT           0x0001
+#define NSSOperations_DECRYPT           0x0002
+#define NSSOperations_WRAP              0x0004
+#define NSSOperations_UNWRAP            0x0008
+#define NSSOperations_SIGN              0x0010
+#define NSSOperations_SIGN_RECOVER      0x0020
+#define NSSOperations_VERIFY            0x0040
+#define NSSOperations_VERIFY_RECOVER    0x0080
+#define NSSOperations_DERIVE            0x0100
+
+typedef PRUint32 NSSProperties;
+
+#define NSSProperties_PRIVATE          0x0001
+#define NSSProperties_READ_ONLY        0x0002
+#define NSSProperties_SENSITIVE        0x0004 /* keys only */
+#define NSSProperties_EXTRACTABLE      0x0008 /* keys only */
+
 struct version_str
 {
   PRUint32 major;
   PRUint32 minor;
 };
 
 
 typedef struct
@@ -140,362 +474,11 @@ typedef struct
   PRBool isLoginRequired;
   PRBool isPINInitialized;
   PRBool hasClock;
   PRBool hasProtectedAuthPath;
   PRBool supportsDualCrypto;
 } 
 NSSTokenInfo;
 
-/*
- * NSSCallback
- *
- * At minimum, a "challenge" method and a closure argument.
- * Usually the challenge will just be prompting for a password.
- * How OO do we want to make it?
- */
-
-typedef struct NSSCallbackStr NSSCallback;
-
-struct NSSCallbackStr {
-    /* Prompt for a password to initialize a slot.  */
-    PRStatus (* getInitPW)(NSSUTF8 *slotName, void *arg, NSSUTF8 **password); 
-    /* Prompt for slot password.  */
-    PRStatus (* getPW)(NSSUTF8 *slotName, PRBool *retry, void *arg,
-                       NSSUTF8 **password); 
-    void *arg;
-};
-
-typedef enum {
-  NSSCertificateType_Unknown = 0,
-  NSSCertificateType_PKIX = 1
-} NSSCertificateType;
-
-typedef enum
-{
-  NSSKeyPairType_Unknown = 0,
-  NSSKeyPairType_RSA = 1,
-  NSSKeyPairType_DSA = 2,
-  NSSKeyPairType_DiffieHellman = 3
-} NSSKeyPairType;
-
-typedef struct NSSRSAPublicKeyInfoStr
-{
-  NSSItem modulus;
-  NSSItem publicExponent;
-}
-NSSRSAPublicKeyInfo;
-
-typedef struct NSSDSAPublicKeyInfoStr
-{
-#if 0
-  NSSPQGParameters params;
-#endif
-  NSSItem publicValue;
-}
-NSSDSAPublicKeyInfo;
-
-typedef struct NSSDHPublicKeyInfoStr
-{
-  NSSItem prime;
-  NSSItem base;
-  NSSItem publicValue;
-}
-NSSDHPublicKeyInfo;
-
-typedef struct NSSPublicKeyInfoStr
-{
-  NSSKeyPairType kind;
-  union {
-    NSSRSAPublicKeyInfo rsa;
-    NSSDSAPublicKeyInfo dsa;
-    NSSDHPublicKeyInfo  dh;
-  } u;
-}
-NSSPublicKeyInfo;
-
-typedef enum
-{
-  NSSSymmetricKeyType_Unknown = 0,
-  NSSSymmetricKeyType_DES = 1,
-  NSSSymmetricKeyType_TripleDES = 2,
-  NSSSymmetricKeyType_RC2 = 3,
-  NSSSymmetricKeyType_RC4 = 4,
-  NSSSymmetricKeyType_RC5 = 5,
-  NSSSymmetricKeyType_AES = 6
-} NSSSymmetricKeyType;
-
-/* set errors - user cancelled, ... */
-
-typedef enum {
-  NSSAlgorithmType_NULL   =  0,
-  NSSAlgorithmType_RSA    =  1,
-  NSSAlgorithmType_DSA    =  2,
-  NSSAlgorithmType_DH     =  3,
-  NSSAlgorithmType_DES    =  4,
-  NSSAlgorithmType_3DES   =  5,
-  NSSAlgorithmType_AES    =  6,
-  NSSAlgorithmType_RC2    =  7,
-  NSSAlgorithmType_RC4    =  8,
-  NSSAlgorithmType_RC5    =  9,
-  NSSAlgorithmType_MD2    = 10,
-  NSSAlgorithmType_MD5    = 11,
-  NSSAlgorithmType_SHA1   = 12,
-  NSSAlgorithmType_PBE    = 13,
-  NSSAlgorithmType_MAC    = 14,
-  NSSAlgorithmType_HMAC   = 15
-} NSSAlgorithmType;
-
-/*
- * RSA
- */
-
-/* key generation */
-typedef struct NSSRSAKeyGenParametersStr
-{
-  PRUint32 modulusBits;
-  PRUint32 publicExponent;
-}
-NSSRSAKeyGenParameters;
-
-/*
- * cipher operations
- * DEFAULT: RAW (X.509)
- */
-typedef enum {
-  NSSRSABlockFormat_RAW              = 0,
-  NSSRSABlockFormat_PKCS1            = 1,
-  NSSRSABlockFormat_PKCS1_WITH_MD2   = 2,
-  NSSRSABlockFormat_PKCS1_WITH_MD5   = 3,
-  NSSRSABlockFormat_PKCS1_WITH_SHA1  = 4,
-  NSSRSABlockFormat_PKCS1_OAEP       = 5
-} NSSRSABlockFormat;
-
-typedef NSSRSABlockFormat NSSRSAParameters;
-
-/*
- * DSA
- */
-
-/* key generation */
-typedef struct NSSDSAKeyGenParametersStr
-{
-  PRUint32 primeBits;
-  NSSItem p, q, g;          /* set of PQG parameters (can be zero)    */
-}
-NSSDSAKeyGenParameters;
-
-/*
- * signature/verification
- * DEFAULT: "raw" (no hashing)
- */
-typedef NSSAlgorithmType NSSDSAParameters; /* hash algorithm */
-
-/*
- * Diffie-Hellman
- */
-
-/*
- * key generation
- *
- * Note: the size of p and g in Diffie-Hellman is not bounded above.
- * The parameters must use an unconstrained datum to represent p and g.
- * The memory used for p and g below is within the scope of the caller,
- * any NSS function will copy as necessary.
- */
-typedef struct NSSDHParametersStr 
-{
-  PRUint32 valueBits;
-  PRUint32 primeBits;
-  NSSItem p, g; /* P and G values (can be zero) */
-}
-NSSDHKeyGenParameters;
-
-/*
- * DES and Triple-DES
- */
-
-/* key generation */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_DESKeyGen;
-
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_3DESKeyGen;
-
-/* 
- * encryption/decryption parameters 
- * DEFAULT: ECB mode
- */
-typedef struct NSSDESParametersStr
-{
-  PRBool pkcsPad;
-  NSSItem iv;
-}
-NSSDESParameters;
-
-/*
- * AES
- */
-
-/* key generation */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_AESKeyGen;
-
-/* encryption/decryption parameters */
-typedef struct NSSAESParametersStr
-{
-#if 0
-  /* PKCS #11 is assuming 128-bit blocks */
-  PRUint32 blockSizeInBits;
-#endif
-  PRBool pkcsPad;
-  NSSItem iv;
-}
-NSSAESParameters;
-
-/*
- * RC2
- */
-
-/* key generation */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_RC2KeyGen;
-
-/* encryption/decryption parameters */
-typedef struct NSSRC2ParametersStr
-{
-  PRUint32 effectiveKeySizeInBits;
-  PRBool pkcsPad;
-  NSSItem iv;
-}
-NSSRC2Parameters;
-
-/*
- * RC4
- */
-
-/* key generation */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_RC4KeyGen;
-
-/* encryption/decryption (parameters are always NULL) */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_RC4;
-
-/*
- * RC5
- */
-
-/* key generation */
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_RC5KeyGen;
-
-/* encryption/decryption parameters */
-typedef struct NSSRC5ParametersStr
-{
-  PRUint32 wordSize;
-  PRUint32 numRounds;
-  PRBool pkcsPad;
-  NSSItem iv;
-}
-NSSRC5Parameters;
-
-/* 
- * MD2 
- */
-
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_MD2;
-
-/* 
- * MD5 
- */
-
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_MD5;
-
-/* 
- * SHA-1 
- */
-
-NSS_EXTERN_DATA const NSSAlgorithmAndParameters *
-                      NSSAlgorithmAndParameters_SHA1;
-
-/*
- * HMAC
- *
- * DEFAULT: maximum length, specific to hash algorithm
- */
-
-typedef PRUint32 NSSHMACParameters; /* length in bytes of desired output */
-
-/*
- * Key derivation
- */
-
-#if 0
-typedef struct NSSKeyDerivationParametersStr
-{
-}
-NSSKeyDerivationParameters;
-#endif
-
-/*
- * PBE key generation
- */
-
-/* NSS will always copy from this data */
-typedef struct NSSPBEKeyGenParametersStr
-{
-  NSSItem iv;
-  NSSUTF8 *password;
-  NSSItem salt;
-  PRUint32 iterations;
-}
-NSSPBEKeyGenParameters;
-
-/* XXX */
-typedef enum {
-  NSSSSLVersion_v2 = 0,
-  NSSSSLVersion_v3 = 1,
-  NSSSSLVersion_TLS = 2
-} NSSSSLVersion;
-
-typedef union
-{
-  NSSRSAKeyGenParameters rsakg;
-  NSSDSAKeyGenParameters dsakg;
-  NSSDHKeyGenParameters  dhkg;
-  NSSPBEKeyGenParameters pbekg;
-  NSSRSAParameters       rsa;
-  NSSDSAParameters       dsa;
-  NSSDESParameters       des;
-  NSSAESParameters       aes;
-  NSSRC2Parameters       rc2;
-  NSSRC5Parameters       rc5;
-  NSSHMACParameters      hmac;
-}
-NSSParameters;
-
-typedef PRUint32 NSSOperations;
-/* 1) Do we want these to be preprocessor definitions or constants? */
-/* 2) What is the correct and complete list? */
-
-#define NSSOperations_ENCRYPT           0x0001
-#define NSSOperations_DECRYPT           0x0002
-#define NSSOperations_WRAP              0x0004
-#define NSSOperations_UNWRAP            0x0008
-#define NSSOperations_SIGN              0x0010
-#define NSSOperations_SIGN_RECOVER      0x0020
-#define NSSOperations_VERIFY            0x0040
-#define NSSOperations_VERIFY_RECOVER    0x0080
-#define NSSOperations_DERIVE            0x0100
-
-typedef PRUint32 NSSProperties;
-
-#define NSSProperties_PRIVATE          0x0001
-#define NSSProperties_READ_ONLY        0x0002
-#define NSSProperties_SENSITIVE        0x0004 /* keys only */
-#define NSSProperties_EXTRACTABLE      0x0008 /* keys only */
-
 PR_END_EXTERN_C
 
 #endif /* NSSDEVT_H */