changeset 3708:75f7822ae9dc

PSARC/2007/093 Crypto Context sharing between providers 6494834 support check for threshold when using hardware providers even for multi-part requests
author krishna
date Fri, 23 Feb 2007 11:55:36 -0800
parents 79eeee281443
children 021a463305e1
files usr/src/cmd/mdb/common/modules/crypto/impl.c usr/src/cmd/mdb/common/modules/crypto/spi.c usr/src/common/crypto/arcfour/arcfour.h usr/src/common/crypto/arcfour/sun4u/arcfour_crypt_asm.s usr/src/uts/common/crypto/api/kcf_cipher.c usr/src/uts/common/crypto/api/kcf_ctxops.c usr/src/uts/common/crypto/api/kcf_miscapi.c usr/src/uts/common/crypto/api/kcf_random.c usr/src/uts/common/crypto/core/kcf.c usr/src/uts/common/crypto/core/kcf_callprov.c usr/src/uts/common/crypto/core/kcf_cryptoadm.c usr/src/uts/common/crypto/core/kcf_mech_tabs.c usr/src/uts/common/crypto/core/kcf_prov_tabs.c usr/src/uts/common/crypto/core/kcf_sched.c usr/src/uts/common/crypto/io/arcfour.c usr/src/uts/common/crypto/io/crypto.c usr/src/uts/common/crypto/io/dprov.c usr/src/uts/common/crypto/spi/kcf_spi.c usr/src/uts/common/sys/crypto/common.h usr/src/uts/common/sys/crypto/impl.h usr/src/uts/common/sys/crypto/ops_impl.h usr/src/uts/common/sys/crypto/sched_impl.h usr/src/uts/common/sys/crypto/spi.h usr/src/uts/sun4v/sys/n2cp.h
diffstat 24 files changed, 316 insertions(+), 235 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/crypto/impl.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/cmd/mdb/common/modules/crypto/impl.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -162,17 +161,18 @@
 			(uintptr_t)mech_pointer, DCMD_ADDRSPEC, 0, NULL);
 	}
 	mdb_dec_indent(4);
-	mdb_printf("pd_map_mechnums:\n");
+	mdb_printf("pd_mech_indx:\n");
 	mdb_inc_indent(8);
 	for (i = 0; i < KCF_OPS_CLASSSIZE; i++) {
 	    for (j = 0; j < KCF_MAXMECHTAB; j++) {
-		mdb_printf("%llu ",
-		    desc.pd_map_mechnums[i][j]);
+		if (desc.pd_mech_indx[i][j] == KCF_INVALID_INDX)
+			mdb_printf("N ");
+		else
+			mdb_printf("%u ", desc.pd_mech_indx[i][j]);
 	    }
 	    mdb_printf("\n");
 	}
 	mdb_dec_indent(8);
-	mdb_printf("pd_stats:\t\t%p\n", desc.pd_stats);
 	mdb_printf("pd_ks_data.ps_ops_total:\n", desc.pd_ks_data.ps_ops_total);
 	pr_kstat_named(&desc.pd_ks_data.ps_ops_total);
 	mdb_printf("pd_ks_data.ps_ops_passed:\n",
@@ -216,8 +216,13 @@
 
 	mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque);
 	mdb_printf("pd_remove_cv:\t\t%hd\n", desc.pd_remove_cv._opaque);
-	mdb_printf("pd_restricted:\t\t%s\n",
-	    desc.pd_restricted == B_FALSE ? "B_FALSE" : "B_TRUE");
+	mdb_printf("pd_flags:\t\t%s %s %s\n",
+	    (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ?
+		"CRYPTO_HIDE_PROVIDER" : " ",
+	    (desc.pd_flags & KCF_LPROV_MEMBER) ?
+		"KCF_LPROV_MEMBER" : " ",
+	    (desc.pd_flags & KCF_PROV_RESTRICTED) ?
+		"KCF_PROV_RESTRICTED" : " ");
 	mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list);
 	return (DCMD_OK);
 }
--- a/usr/src/cmd/mdb/common/modules/crypto/spi.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/cmd/mdb/common/modules/crypto/spi.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -206,7 +205,7 @@
 	mdb_printf("cm_mech_number\t%lld\n", minfo.cm_mech_number);
 	mdb_printf("cm_func_group_mask\t0x%x:\t<%b>\n",
 	    minfo.cm_func_group_mask, minfo.cm_func_group_mask, mech_bits);
-	if (minfo.cm_keysize_unit != CRYPTO_KEYSIZE_UNIT_IN_BITS)
+	if (minfo.cm_keysize_unit & CRYPTO_KEYSIZE_UNIT_IN_BYTES)
 		unit = "bytes";
 	mdb_printf("cm_min_key_length\t%lu %s\n", minfo.cm_min_key_length,
 	    unit);
--- a/usr/src/common/crypto/arcfour/arcfour.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/common/crypto/arcfour/arcfour.h	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -34,6 +33,7 @@
 #endif
 
 #include <sys/types.h>
+#include <sys/crypto/common.h>
 
 #define	ARCFOUR_MIN_KEY_BYTES	1
 
@@ -46,13 +46,7 @@
 #define	ARCFOUR_MIN_KEY_BITS	(ARCFOUR_MIN_KEY_BYTES << 3)
 #define	ARCFOUR_MAX_KEY_BITS	(ARCFOUR_MAX_KEY_BYTES << 3)
 
-typedef struct {
-	uchar_t i, j;
-#ifdef	sun4v
-	unsigned long long pad;
-#endif	/* sun4v */
-	uchar_t arr[256];
-} ARCFour_key;
+typedef arcfour_state_t ARCFour_key;
 
 void arcfour_key_init(ARCFour_key *key, uchar_t *keyval, int keyvallen);
 void arcfour_crypt(ARCFour_key *key, uchar_t *in, uchar_t *out, size_t len);
--- a/usr/src/common/crypto/arcfour/sun4u/arcfour_crypt_asm.s	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/common/crypto/arcfour/sun4u/arcfour_crypt_asm.s	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -61,14 +60,14 @@
 	save	%sp,-144,%sp
 
 	srl	%i1, 3, %l7
-	ldub	[%i0], %g1
+	ldub	[%i0+256], %g1
 
 	orcc	%l7, %g0, %g0
-	ldub	[%i0+1], %g2
+	ldub	[%i0+257], %g2
 
 	add	%g1, 1, %o1
 	bz	%icc, .Loop2
-	add	%i0, 2, %i5
+	add	%i0, 0, %i5
 
 	add	%o1, 1, %g1
 	and	%o1, 255, %o1
@@ -409,7 +408,7 @@
 	sub	%g1, 2, %g1
 
 	and	%g1, 255, %g1
-	stb	%g1, [%i0]
+	stb	%g1, [%i0 + 256]
 	or	%o0, %g5, %o0
 
 	xor	%o0, %o7, %o7
@@ -418,7 +417,7 @@
 
 	add	%i3, 8, %i3
 	bnz	%icc, .Loop2_1
-	stb	%g2, [%i0 + 1]
+	stb	%g2, [%i0 + 257]
 	
 	ret	
 	restore	%g0,%g0,%g0
@@ -460,9 +459,9 @@
 	bnz	%icc, .Loop2_1
 	stb	%o0, [%i3 - 1]
 
-	stb	%g1, [%i0]
+	stb	%g1, [%i0 + 256]
 
-	stb	%g2, [%i0 + 1]
+	stb	%g2, [%i0 + 257]
 	
 	ret
 	restore	%g0,%g0,%g0
--- a/usr/src/uts/common/crypto/api/kcf_cipher.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/api/kcf_cipher.c	Fri Feb 23 11:55:36 2007 -0800
@@ -157,23 +157,62 @@
 			    &lmech, key, tmpl, KCF_SWFP_RHNDL(crq));
 		}
 		KCF_PROV_INCRSTATS(pd, error);
+
+		goto done;
+	}
+
+	/* Check if context sharing is possible */
+	if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
+	    key->ck_format == CRYPTO_KEY_RAW &&
+	    KCF_CAN_SHARE_OPSTATE(pd, mech->cm_type)) {
+		kcf_context_t *tctxp = (kcf_context_t *)ctx;
+		kcf_provider_desc_t *tpd = NULL;
+		crypto_mech_info_t *sinfo;
+
+		if ((kcf_get_sw_prov(mech->cm_type, &tpd, &tctxp->kc_mech,
+		    B_FALSE) == CRYPTO_SUCCESS)) {
+			int tlen;
+
+			sinfo = &(KCF_TO_PROV_MECHINFO(tpd, mech->cm_type));
+			/*
+			 * key->ck_length from the consumer is always in bits.
+			 * We convert it to be in the same unit registered by
+			 * the provider in order to do a comparison.
+			 */
+			if (sinfo->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BYTES)
+				tlen = key->ck_length >> 3;
+			else
+				tlen = key->ck_length;
+			/*
+			 * Check if the software provider can support context
+			 * sharing and support this key length.
+			 */
+			if ((sinfo->cm_mech_flags & CRYPTO_CAN_SHARE_OPSTATE) &&
+			    (tlen >= sinfo->cm_min_key_length) &&
+			    (tlen <= sinfo->cm_max_key_length)) {
+				ctx->cc_flags = CRYPTO_INIT_OPSTATE;
+				tctxp->kc_sw_prov_desc = tpd;
+			} else
+				KCF_PROV_REFRELE(tpd);
+		}
+	}
+
+	if (func == CRYPTO_FG_ENCRYPT) {
+		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
+		    mech, key, NULL, NULL, tmpl);
 	} else {
-		if (func == CRYPTO_FG_ENCRYPT) {
-			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
-			    mech, key, NULL, NULL, tmpl);
-		} else {
-			ASSERT(func == CRYPTO_FG_DECRYPT);
-			KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
-			    mech, key, NULL, NULL, tmpl);
-		}
+		ASSERT(func == CRYPTO_FG_DECRYPT);
+		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
+		    mech, key, NULL, NULL, tmpl);
+	}
 
-		error = kcf_submit_request(real_provider, ctx, crq, &params,
-		    B_FALSE);
-	}
+	error = kcf_submit_request(real_provider, ctx, crq, &params,
+	    B_FALSE);
 
 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
 		KCF_PROV_REFRELE(real_provider);
 
+done:
 	if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
 		*ctxp = (crypto_context_t)ctx;
 	else {
@@ -457,12 +496,22 @@
 		error = KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext,
 		    ciphertext, NULL);
 		KCF_PROV_INCRSTATS(pd, error);
-	} else {
-		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
-		    ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL);
-		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+		return (error);
 	}
 
+	/* Check if we should use a software provider for small jobs */
+	if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && cr == NULL) {
+		if (plaintext->cd_length < kcf_ctx->kc_mech->me_threshold &&
+		    kcf_ctx->kc_sw_prov_desc != NULL &&
+		    KCF_IS_PROV_USABLE(kcf_ctx->kc_sw_prov_desc)) {
+			pd = kcf_ctx->kc_sw_prov_desc;
+		}
+	}
+
+	KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
+	    ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL);
+	error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+
 	return (error);
 }
 
@@ -730,12 +779,22 @@
 		error = KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext,
 		    plaintext, NULL);
 		KCF_PROV_INCRSTATS(pd, error);
-	} else {
-		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
-		    ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL);
-		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+		return (error);
 	}
 
+	/* Check if we should use a software provider for small jobs */
+	if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && cr == NULL) {
+		if (ciphertext->cd_length < kcf_ctx->kc_mech->me_threshold &&
+		    kcf_ctx->kc_sw_prov_desc != NULL &&
+		    KCF_IS_PROV_USABLE(kcf_ctx->kc_sw_prov_desc)) {
+			pd = kcf_ctx->kc_sw_prov_desc;
+		}
+	}
+
+	KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
+	    ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL);
+	error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+
 	return (error);
 }
 
@@ -810,7 +869,6 @@
 		return (CRYPTO_INVALID_CONTEXT);
 	}
 
-
 	/* The fast path for SW providers. */
 	if (CHECK_FASTPATH(cr, pd)) {
 		error = KCF_PROV_ENCRYPT(pd, ctx, plaintext,
@@ -846,7 +904,6 @@
 		return (CRYPTO_INVALID_CONTEXT);
 	}
 
-
 	/* The fast path for SW providers. */
 	if (CHECK_FASTPATH(cr, pd)) {
 		error = KCF_PROV_DECRYPT(pd, ctx, ciphertext,
--- a/usr/src/uts/common/crypto/api/kcf_ctxops.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/api/kcf_ctxops.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -79,12 +78,9 @@
 {
 	int error;
 	kcf_mech_entry_t *me;
-	kcf_prov_mech_desc_t *pm;
 	kcf_provider_desc_t *pd;
 	kcf_ctx_template_t *ctx_tmpl;
 	crypto_mechanism_t prov_mech;
-	kcf_ops_class_t class;
-	int index;
 
 	/* A few args validation */
 
@@ -94,24 +90,9 @@
 	if (mech == NULL)
 		return (CRYPTO_MECHANISM_INVALID);
 
-	if (kcf_get_mech_entry(mech->cm_type, &me) != KCF_SUCCESS) {
-		/* error is one of the KCF_INVALID_MECH_XXX's */
-		return (CRYPTO_MECHANISM_INVALID);
-	}
-
-	/*
-	 * Get the software provider for the mech.
-	 * Lock the mech_entry until we grab the 'pd'
-	 */
-	mutex_enter(&me->me_mutex);
-
-	if (((pm = me->me_sw_prov) == NULL) ||
-	    ((pd = pm->pm_prov_desc) == NULL)) {
-		mutex_exit(&me->me_mutex);
-		return (CRYPTO_MECH_NOT_SUPPORTED);
-	}
-	KCF_PROV_REFHOLD(pd);
-	mutex_exit(&me->me_mutex);
+	error = kcf_get_sw_prov(mech->cm_type, &pd, &me, B_TRUE);
+	if (error != CRYPTO_SUCCESS)
+		return (error);
 
 	if ((ctx_tmpl = (kcf_ctx_template_t *)kmem_alloc(
 	    sizeof (kcf_ctx_template_t), kmflag)) == NULL) {
@@ -120,9 +101,7 @@
 	}
 
 	/* Pass a mechtype that the provider understands */
-	class = KCF_MECH2CLASS(mech->cm_type);
-	index = KCF_MECH2INDEX(mech->cm_type);
-	prov_mech.cm_type = pd->pd_map_mechnums[class][index];
+	prov_mech.cm_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type);
 	prov_mech.cm_param = mech->cm_param;
 	prov_mech.cm_param_len = mech->cm_param_len;
 
--- a/usr/src/uts/common/crypto/api/kcf_miscapi.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/api/kcf_miscapi.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -616,8 +616,8 @@
 	crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask;
 
 	/* min/max key sizes */
-	mech_info->mi_keysize_unit =
-	    pmd->pm_mech_info.cm_keysize_unit;
+	mech_info->mi_keysize_unit = pmd->pm_mech_info.cm_mech_flags &
+	    (CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_KEYSIZE_UNIT_IN_BYTES);
 	mech_info->mi_min_key_size =
 	    (size_t)pmd->pm_mech_info.cm_min_key_length;
 	mech_info->mi_max_key_size =
--- a/usr/src/uts/common/crypto/api/kcf_random.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/api/kcf_random.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -200,7 +200,8 @@
 {
 	kcf_provider_desc_t *pd = NULL;
 
-	if (kcf_get_sw_prov(rngmech_type, &pd, B_FALSE) == CRYPTO_SUCCESS) {
+	if (kcf_get_sw_prov(rngmech_type, &pd, NULL, B_FALSE) ==
+	    CRYPTO_SUCCESS) {
 		(void) KCF_PROV_SEED_RANDOM(pd, pd->pd_sid, buf, len,
 		    entropy_est, flags, NULL);
 		KCF_PROV_REFRELE(pd);
--- a/usr/src/uts/common/crypto/core/kcf.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -260,12 +259,9 @@
 			error = 0;
 		}
 
-		pd->pd_restricted =
-		    (rkda->da_u.result.status == ELFSIGN_RESTRICTED);
-
-		if (pd->pd_restricted) {
-			KCF_FRMWRK_DEBUG(2,
-			    ("provider is restricted\n"));
+		if (rkda->da_u.result.status == ELFSIGN_RESTRICTED) {
+			pd->pd_flags |= KCF_PROV_RESTRICTED;
+			KCF_FRMWRK_DEBUG(2, ("provider is restricted\n"));
 		}
 
 		if (rkda != kda)
--- a/usr/src/uts/common/crypto/core/kcf_callprov.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf_callprov.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -183,7 +183,8 @@
 			ASSERT(provider->pd_prov_type !=
 			    CRYPTO_LOGICAL_PROVIDER);
 
-			if (call_restrict && provider->pd_restricted) {
+			if (call_restrict &&
+			    (provider->pd_flags & KCF_PROV_RESTRICTED)) {
 				p = p->pl_next;
 				continue;
 			}
@@ -195,21 +196,11 @@
 
 			/* provider does second mech */
 			if (mech_type_2 != CRYPTO_MECH_INVALID) {
-				crypto_mech_type_t mech_type;
 				int i;
 
-				/* convert from kef to provider's number */
-				mech_type = provider->pd_map_mechnums
-				    [KCF_MECH2CLASS(mech_type_2)]
-				    [KCF_MECH2INDEX(mech_type_2)];
-
-				for (i = 0; i < provider->pd_mech_list_count;
-				    i++) {
-					if (provider->pd_mechanisms[i]
-					    .cm_mech_number == mech_type)
-						break;
-				}
-				if (i == provider->pd_mech_list_count) {
+				i = KCF_TO_PROV_MECH_INDX(provider,
+				    mech_type_2);
+				if (i == KCF_INVALID_INDX) {
 					p = p->pl_next;
 					continue;
 				}
@@ -247,7 +238,7 @@
 
 	} else {
 		if (!KCF_IS_PROV_USABLE(old) ||
-		    (call_restrict && old->pd_restricted)) {
+		    (call_restrict && (old->pd_flags & KCF_PROV_RESTRICTED))) {
 			real_pd = NULL;
 			rv = CRYPTO_DEVICE_ERROR;
 			goto out;
@@ -315,7 +306,8 @@
 			ASSERT(provider->pd_prov_type !=
 			    CRYPTO_LOGICAL_PROVIDER);
 
-			if (call_restrict && provider->pd_restricted) {
+			if (call_restrict &&
+			    (provider->pd_flags & KCF_PROV_RESTRICTED)) {
 				p = p->pl_next;
 				continue;
 			}
@@ -357,7 +349,7 @@
 
 	} else {
 		if (!KCF_IS_PROV_USABLE(old) ||
-		    (call_restrict && old->pd_restricted)) {
+		    (call_restrict && (old->pd_flags & KCF_PROV_RESTRICTED))) {
 			real_pd = NULL;
 			rv = CRYPTO_DEVICE_ERROR;
 			goto out;
@@ -468,7 +460,7 @@
 	 */
 	if ((prov_chain != NULL) &&
 	    ((data_size == 0) || (me->me_threshold == 0) ||
-	    (data_size > me->me_threshold) ||
+	    (data_size >= me->me_threshold) ||
 	    ((mdesc = me->me_sw_prov) == NULL) ||
 	    (!IS_FG_SUPPORTED(mdesc, fg)) ||
 	    (!KCF_IS_PROV_USABLE(mdesc->pm_prov_desc)))) {
@@ -488,7 +480,8 @@
 			if (!IS_FG_SUPPORTED(prov_chain, fg) ||
 			    !KCF_IS_PROV_USABLE(pd) ||
 			    IS_PROVIDER_TRIED(pd, triedl) ||
-			    (call_restrict && pd->pd_restricted)) {
+			    (call_restrict &&
+				(pd->pd_flags & KCF_PROV_RESTRICTED))) {
 				prov_chain = prov_chain->pm_next;
 				continue;
 			}
@@ -511,7 +504,7 @@
 		if (!IS_FG_SUPPORTED(mdesc, fg) ||
 		    !KCF_IS_PROV_USABLE(pd) ||
 		    IS_PROVIDER_TRIED(pd, triedl) ||
-		    (call_restrict && pd->pd_restricted))
+		    (call_restrict && (pd->pd_flags & KCF_PROV_RESTRICTED)))
 			pd = NULL;
 	}
 
@@ -574,7 +567,7 @@
 	 */
 	if ((prov_chain != NULL) &&
 	    ((data_size == 0) || (me->me_threshold == 0) ||
-	    (data_size > me->me_threshold) ||
+	    (data_size >= me->me_threshold) ||
 	    ((mdesc = me->me_sw_prov) == NULL) ||
 	    (!IS_FG_SUPPORTED(mdesc, fg1)) ||
 	    (!KCF_IS_PROV_USABLE(mdesc->pm_prov_desc)))) {
@@ -593,7 +586,8 @@
 			if (!IS_FG_SUPPORTED(prov_chain, fg1) ||
 			    !KCF_IS_PROV_USABLE(pd) ||
 			    IS_PROVIDER_TRIED(pd, triedl) ||
-			    (call_restrict && pd->pd_restricted)) {
+			    (call_restrict &&
+				(pd->pd_flags & KCF_PROV_RESTRICTED))) {
 				prov_chain = prov_chain->pm_next;
 				continue;
 			}
@@ -638,7 +632,7 @@
 		if (!IS_FG_SUPPORTED(mdesc, fg1) ||
 		    !KCF_IS_PROV_USABLE(pd) ||
 		    IS_PROVIDER_TRIED(pd, triedl) ||
-		    (call_restrict && pd->pd_restricted))
+		    (call_restrict && (pd->pd_flags & KCF_PROV_RESTRICTED)))
 			pd = NULL;
 		else {
 			/* See if pd can do me2 too */
--- a/usr/src/uts/common/crypto/core/kcf_cryptoadm.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf_cryptoadm.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -364,7 +364,7 @@
 
 		switch (direction) {
 		case CRYPTO_MECH_ADDED:
-			(void) kcf_add_mech_provider(mi, provider, &pmd);
+			(void) kcf_add_mech_provider(j, provider, &pmd);
 			break;
 
 		case CRYPTO_MECH_REMOVED:
--- a/usr/src/uts/common/crypto/core/kcf_mech_tabs.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf_mech_tabs.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -341,7 +341,7 @@
  * kcf_add_mech_provider()
  *
  * Arguments:
- *	. A pointer to the mechanism info
+ *	. An index in to  the provider mechanism array
  *      . A pointer to the provider descriptor
  *	. A storage for the kcf_prov_mech_desc_t the entry was added at.
  *
@@ -357,11 +357,12 @@
  *      KCF_MECH_TAB_FULL otherwise.
  */
 int
-kcf_add_mech_provider(crypto_mech_info_t *mech_info,
+kcf_add_mech_provider(short mech_indx,
     kcf_provider_desc_t *prov_desc, kcf_prov_mech_desc_t **pmdpp)
 {
 	int error;
 	kcf_mech_entry_t *mech_entry;
+	crypto_mech_info_t *mech_info;
 	crypto_mech_type_t kcf_mech_type, mt;
 	kcf_prov_mech_desc_t *prov_mech, *prov_mech2;
 	crypto_func_group_t simple_fg_mask, dual_fg_mask;
@@ -372,6 +373,7 @@
 
 	ASSERT(prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
 
+	mech_info = &prov_desc->pd_mechanisms[mech_indx];
 	/*
 	 * Do not use the provider for the mechanism if
 	 * policy does not allow it.
@@ -434,8 +436,9 @@
 	prov_mech = kmem_zalloc(sizeof (kcf_prov_mech_desc_t), KM_SLEEP);
 	bcopy(mech_info, &prov_mech->pm_mech_info, sizeof (crypto_mech_info_t));
 	prov_mech->pm_prov_desc = prov_desc;
-	prov_desc->pd_map_mechnums[KCF_MECH2CLASS(kcf_mech_type)]
-	    [KCF_MECH2INDEX(kcf_mech_type)] = mech_info->cm_mech_number;
+	prov_desc->pd_mech_indx[KCF_MECH2CLASS(kcf_mech_type)]
+	    [KCF_MECH2INDEX(kcf_mech_type)] = mech_indx;
+
 	KCF_PROV_REFHOLD(prov_desc);
 	KCF_PROV_IREFHOLD(prov_desc);
 
--- a/usr/src/uts/common/crypto/core/kcf_prov_tabs.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf_prov_tabs.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -290,6 +289,7 @@
 kcf_provider_desc_t *
 kcf_alloc_provider_desc(crypto_provider_info_t *info)
 {
+	int i, j;
 	kcf_provider_desc_t *desc;
 	uint_t mech_list_count = info->pi_mech_list_count;
 	crypto_ops_t *src_ops = info->pi_ops_vector;
@@ -329,8 +329,12 @@
 	}
 
 	desc->pd_mech_list_count = mech_list_count;
-	desc->pd_mechanisms = kmem_alloc(sizeof (crypto_mech_info_t) *
+	desc->pd_mechanisms = kmem_zalloc(sizeof (crypto_mech_info_t) *
 	    mech_list_count, KM_SLEEP);
+	for (i = 0; i < KCF_OPS_CLASSSIZE; i++)
+		for (j = 0; j < KCF_MAXMECHTAB; j++)
+			desc->pd_mech_indx[i][j] = KCF_INVALID_INDX;
+
 	desc->pd_prov_id = KCF_PROVID_INVALID;
 	desc->pd_state = KCF_PROV_ALLOCATED;
 
@@ -756,14 +760,15 @@
  * Returns in the location pointed to by pd a pointer to the descriptor
  * for the software provider for the specified mechanism.
  * The provider descriptor is returned held and it is the caller's
- * responsibility to release it when done.
+ * responsibility to release it when done. The mechanism entry
+ * is returned if the optional argument mep is non NULL.
  *
  * Returns one of the CRYPTO_ * error codes on failure, and
  * CRYPTO_SUCCESS on success.
  */
 int
 kcf_get_sw_prov(crypto_mech_type_t mech_type, kcf_provider_desc_t **pd,
-    boolean_t log_warn)
+    kcf_mech_entry_t **mep, boolean_t log_warn)
 {
 	kcf_mech_entry_t *me;
 
@@ -771,10 +776,14 @@
 	if (kcf_get_mech_entry(mech_type, &me) != KCF_SUCCESS)
 		return (CRYPTO_MECHANISM_INVALID);
 
-	/* get a software provider for this mechanism */
+	/*
+	 * Get the software provider for this mechanism.
+	 * Lock the mech_entry until we grab the 'pd'.
+	 */
 	mutex_enter(&me->me_mutex);
 
-	if (me->me_sw_prov == NULL) {
+	if (me->me_sw_prov == NULL ||
+	    (*pd = me->me_sw_prov->pm_prov_desc) == NULL) {
 		/* no SW provider for this mechanism */
 		if (log_warn)
 			cmn_err(CE_WARN, "no SW provider for \"%s\"\n",
@@ -783,10 +792,12 @@
 		return (CRYPTO_MECH_NOT_SUPPORTED);
 	}
 
-	*pd = me->me_sw_prov->pm_prov_desc;
 	KCF_PROV_REFHOLD(*pd);
 	mutex_exit(&me->me_mutex);
 
+	if (mep != NULL)
+		*mep = me;
+
 	return (CRYPTO_SUCCESS);
 }
 
--- a/usr/src/uts/common/crypto/core/kcf_sched.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/core/kcf_sched.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -124,12 +124,16 @@
 	kcf_ctx->kc_secondctx = NULL;
 	KCF_PROV_REFHOLD(pd);
 	kcf_ctx->kc_prov_desc = pd;
+	kcf_ctx->kc_sw_prov_desc = NULL;
+	kcf_ctx->kc_mech = NULL;
 
 	ctx = &kcf_ctx->kc_glbl_ctx;
 	ctx->cc_provider = pd->pd_prov_handle;
 	ctx->cc_session = sid;
 	ctx->cc_provider_private = NULL;
 	ctx->cc_framework_private = (void *)kcf_ctx;
+	ctx->cc_flags = 0;
+	ctx->cc_opstate = NULL;
 
 	return (ctx);
 }
@@ -825,6 +829,12 @@
 	/* kcf_ctx->kc_prov_desc has a hold on pd */
 	KCF_PROV_REFRELE(kcf_ctx->kc_prov_desc);
 
+	/* check if this context is shared with a software provider */
+	if ((gctx->cc_flags & CRYPTO_INIT_OPSTATE) &&
+	    kcf_ctx->kc_sw_prov_desc != NULL) {
+		KCF_PROV_REFRELE(kcf_ctx->kc_sw_prov_desc);
+	}
+
 	kmem_cache_free(kcf_context_cache, kcf_ctx);
 }
 
--- a/usr/src/uts/common/crypto/io/arcfour.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/io/arcfour.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -70,7 +69,7 @@
 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
 	    ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
-	    CRYPTO_KEYSIZE_UNIT_IN_BITS}
+	    CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_CAN_SHARE_OPSTATE}
 };
 
 static void rc4_provider_status(crypto_provider_handle_t, uint_t *);
@@ -287,7 +286,10 @@
 
 	ASSERT(ctx->cc_provider_private != NULL);
 
-	key = ctx->cc_provider_private;
+	if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && ctx->cc_opstate != NULL)
+		key = ctx->cc_opstate;
+	else
+		key = ctx->cc_provider_private;
 
 	/* Simple case: in-line encipherment */
 
@@ -527,10 +529,10 @@
     crypto_data_t *output, crypto_spi_ctx_template_t template,
     crypto_req_handle_t req)
 {
-
 	crypto_ctx_t ctx;
 	int ret;
 
+	bzero(&ctx, sizeof (crypto_ctx_t));
 	ret = rc4_common_init(&ctx, mechanism, key, template, req);
 
 	if (ret != CRYPTO_SUCCESS)
--- a/usr/src/uts/common/crypto/io/crypto.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/io/crypto.c	Fri Feb 23 11:55:36 2007 -0800
@@ -2236,14 +2236,10 @@
     crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error)
 {
 	crypto_mech_type_t provider_mech_type;
-	kcf_ops_class_t class;
-	int index;
 	int rv;
 
 	/* get the provider's mech number */
-	class = KCF_MECH2CLASS(umech->cm_type);
-	index = KCF_MECH2INDEX(umech->cm_type);
-	provider_mech_type = pd->pd_map_mechnums[class][index];
+	provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
 
 	kmech->cm_param = NULL;
 	kmech->cm_param_len = 0;
@@ -2272,14 +2268,10 @@
     crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error)
 {
 	crypto_mech_type_t provider_mech_type;
-	kcf_ops_class_t class;
-	int index;
 	int rv;
 
 	/* get the provider's mech number */
-	class = KCF_MECH2CLASS(umech->cm_type);
-	index = KCF_MECH2INDEX(umech->cm_type);
-	provider_mech_type = pd->pd_map_mechnums[class][index];
+	provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
 
 	kmech->cm_type = provider_mech_type;
 	rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode);
@@ -2297,17 +2289,13 @@
     crypto_mechanism_t *mech)
 {
 	crypto_mech_type_t provider_mech_type;
-	kcf_ops_class_t class;
-	int index;
 
 	if (allocated_by_crypto_module) {
 		if (mech->cm_param != NULL)
 			kmem_free(mech->cm_param, mech->cm_param_len);
 	} else {
 		/* get the provider's mech number */
-		class = KCF_MECH2CLASS(mech->cm_type);
-		index = KCF_MECH2INDEX(mech->cm_type);
-		provider_mech_type = pd->pd_map_mechnums[class][index];
+		provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type);
 
 		if (mech->cm_param != NULL && mech->cm_param_len != 0) {
 			mech->cm_type = provider_mech_type;
--- a/usr/src/uts/common/crypto/io/dprov.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/io/dprov.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -465,7 +465,7 @@
 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
 	    ARCFOUR_MIN_KEY_BITS, ARCFOUR_MAX_KEY_BITS,
-	    CRYPTO_KEYSIZE_UNIT_IN_BITS},
+	    CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_CAN_SHARE_OPSTATE},
 	/* RSA_PKCS */
 	{SUN_CKM_RSA_PKCS, RSA_PKCS_MECH_INFO_TYPE,
 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
@@ -5384,6 +5384,14 @@
 			error = crypto_decrypt_init_prov(pd, 0, &mech, keyp,
 			    NULL, &DPROV_CTX_SINGLE(ctx), NULL);
 
+		if (ctx->cc_flags & CRYPTO_INIT_OPSTATE) {
+			crypto_ctx_t *lctx =
+			    (crypto_ctx_t *)(DPROV_CTX_SINGLE(ctx));
+
+			ctx->cc_opstate = lctx->cc_provider_private;
+			ctx->cc_flags |= CRYPTO_USE_OPSTATE;
+		}
+
 		/* release provider reference */
 		KCF_PROV_REFRELE(pd);
 		break;
@@ -5411,12 +5419,16 @@
 		break;
 
 	case DPROV_REQ_ENCRYPT_UPDATE:
+		ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
+		    (ctx->cc_flags & CRYPTO_USE_OPSTATE));
 		error = crypto_encrypt_update(DPROV_CTX_SINGLE(ctx),
 		    taskq_req->dr_cipher_req.dr_plaintext,
 		    taskq_req->dr_cipher_req.dr_ciphertext, NULL);
 		break;
 
 	case DPROV_REQ_DECRYPT_UPDATE:
+		ASSERT(!(ctx->cc_flags & CRYPTO_INIT_OPSTATE) ||
+		    (ctx->cc_flags & CRYPTO_USE_OPSTATE));
 		error = crypto_decrypt_update(DPROV_CTX_SINGLE(ctx),
 		    taskq_req->dr_cipher_req.dr_ciphertext,
 		    taskq_req->dr_cipher_req.dr_plaintext, NULL);
@@ -7608,7 +7620,7 @@
 		}
 	}
 
-	rv = kcf_get_sw_prov(kcf_mech_type, pd, B_TRUE);
+	rv = kcf_get_sw_prov(kcf_mech_type, pd, NULL, B_TRUE);
 	if (rv == CRYPTO_SUCCESS)
 		*provider_mech_type = kcf_mech_type;
 
--- a/usr/src/uts/common/crypto/spi/kcf_spi.c	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/crypto/spi/kcf_spi.c	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -716,12 +716,6 @@
 			(void) strncpy(rand_mi->cm_mech_name, SUN_RANDOM,
 			    CRYPTO_MAX_MECH_NAME);
 			rand_mi->cm_func_group_mask = CRYPTO_FG_RANDOM;
-			/*
-			 * What we really need here is a
-			 * CRYPTO_KEYSIZE_NOT_APPLICABLE. We make do with the
-			 * following for now.
-			 */
-			rand_mi->cm_keysize_unit = CRYPTO_KEYSIZE_UNIT_IN_BITS;
 		} else {
 			ASSERT(info->pi_mechanisms != NULL);
 			bcopy(info->pi_mechanisms, desc->pd_mechanisms,
@@ -736,13 +730,13 @@
 	for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; mech_idx++) {
 		crypto_mech_info_t *mi = &desc->pd_mechanisms[mech_idx];
 
-		if (mi->cm_keysize_unit != CRYPTO_KEYSIZE_UNIT_IN_BITS &&
-		    mi->cm_keysize_unit != CRYPTO_KEYSIZE_UNIT_IN_BYTES) {
+		if ((mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BITS) &&
+		    (mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BYTES)) {
 			err = CRYPTO_ARGUMENTS_BAD;
 			break;
 		}
 
-		if (kcf_add_mech_provider(mi, desc, &pmd) != KCF_SUCCESS)
+		if (kcf_add_mech_provider(mech_idx, desc, &pmd) != KCF_SUCCESS)
 			break;
 
 		if (pmd == NULL)
--- a/usr/src/uts/common/sys/crypto/common.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/sys/crypto/common.h	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -67,13 +67,21 @@
 #endif  /* _SYSCALL32 */
 
 /*
- * The measurement unit flag for a mechanism's minimum or maximum key size.
+ * The measurement unit bit flag for a mechanism's minimum or maximum key size.
  * The unit are mechanism dependant.  It can be in bits or in bytes.
  */
 typedef uint32_t crypto_keysize_unit_t;
 
+/*
+ * The following bit flags are valid in cm_mech_flags field in
+ * the crypto_mech_info_t structure of the SPI.
+ *
+ * Only the first two bit flags are valid in mi_keysize_unit
+ * field in the crypto_mechanism_info_t structure of the API.
+ */
 #define	CRYPTO_KEYSIZE_UNIT_IN_BITS	0x00000001
 #define	CRYPTO_KEYSIZE_UNIT_IN_BYTES	0x00000002
+#define	CRYPTO_CAN_SHARE_OPSTATE	0x00000004 /* supports sharing */
 
 
 /* Mechanisms supported out-of-the-box */
@@ -110,6 +118,13 @@
 #define	SUN_CKM_SHA384_RSA_PKCS		"CKM_SHA384_RSA_PKCS"
 #define	SUN_CKM_SHA512_RSA_PKCS		"CKM_SHA512_RSA_PKCS"
 
+/* Shared operation context format for CKM_RC4 */
+typedef struct {
+	uchar_t arr[256];
+	uchar_t i, j;
+	uint64_t pad;		/* For 64-bit alignment */
+} arcfour_state_t;
+
 
 /* Data arguments of cryptographic operations */
 
--- a/usr/src/uts/common/sys/crypto/impl.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/sys/crypto/impl.h	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -155,11 +155,9 @@
 	(pd)->pd_state == KCF_PROV_BUSY)
 #define	KCF_IS_PROV_REMOVED(pd)	((pd)->pd_state >= KCF_PROV_REMOVED)
 
-/*
- * Internal flag set to indicate if a provider is a member of
- * a logical provider.
- */
-#define	KCF_LPROV_MEMBER	0x80000000
+/* Internal flags valid for pd_flags field */
+#define	KCF_PROV_RESTRICTED	0x40000000
+#define	KCF_LPROV_MEMBER	0x80000000 /* is member of a logical provider */
 
 /*
  * A provider descriptor structure. There is one such structure per
@@ -167,67 +165,64 @@
  * freed when the provider unregisters.
  *
  * pd_prov_type:	Provider type, hardware or software
+ * pd_sid:		Session ID of the provider used by kernel clients.
+ *			This is valid only for session-oriented providers.
+ * pd_refcnt:		Reference counter to this provider descriptor
+ * pd_irefcnt:		References held by the framework internal structs
+ * pd_lock:		lock protects pd_state and pd_provider_list
+ * pd_state:		State value of the provider
+ * pd_provider_list:	Used to cross-reference logical providers and their
+ *			members. Not used for software providers.
+ * pd_resume_cv:	cv to wait for state to change from KCF_PROV_BUSY
  * pd_prov_handle:	Provider handle specified by provider
- * pd_kcf_prov_handle:	KCF-private handle assigned by KCF
- * pd_prov_id:		Identification # assigned by KCF to provider
- * pd_description:	Provider description string
  * pd_ops_vector:	The ops vector specified by Provider
+ * pd_mech_indx:	Lookup table which maps a core framework mechanism
+ *			number to an index in pd_mechanisms array
+ * pd_mechanisms:	Array of mechanisms supported by the provider, specified
+ *			by the provider during registration
+ * pd_sched_info:	Scheduling information associated with the provider
  * pd_mech_list_count:	The number of entries in pi_mechanisms, specified
  *			by the provider during registration
- * pd_mechanisms:	Mechanisms supported by the provider, specified
- *			by the provider during registration
- * pd_map_mechnums:	Lookup table which maps a core framework mechanism
- *			number to a number understood by this provider
- * pd_ks_data:		kstat data
- * pd_kstat:		kstat associated with the provider
- * pd_sched_info:	Scheduling information associated with the provider
- * pd_refcnt:		Reference counter to this provider descriptor
- * pd_irefcnt:		References held by the framework internal structs
  * pd_name:		Device name or module name
  * pd_instance:		Device instance
  * pd_module_id:	Module ID returned by modload
  * pd_mctlp:		Pointer to modctl structure for this provider
- * pd_sid:		Session ID of the provider used by kernel clients.
- *			This is valid only for session-oriented providers.
- * pd_lock:		lock protects pd_state and pd_real_provider_list
- * pd_state:		State value of the provider
- * pd_resume_cv:	cv to wait for state to change from KCF_PROV_BUSY
  * pd_remove_cv:	cv to wait on while the provider queue drains
- * pd_restricted:	true if this is an export restricted provider
- * pd_provider_list:	Used to cross-reference logical providers and their
- *			members. Not used for software providers.
+ * pd_description:	Provider description string
  * pd_flags		Could be CRYPTO_HIDE_PROVIDER from pi_flags
- *			or KCF_LPROV_MEMBER set internally.
+ *			or KCF_LPROV_MEMBER, KCF_PROV_RESTRICTED set internally.
+ * pd_kcf_prov_handle:	KCF-private handle assigned by KCF
+ * pd_prov_id:		Identification # assigned by KCF to provider
+ * pd_kstat:		kstat associated with the provider
+ * pd_ks_data:		kstat data
  */
 typedef struct kcf_provider_desc {
 	crypto_provider_type_t		pd_prov_type;
-	crypto_provider_handle_t	pd_prov_handle;
-	crypto_kcf_provider_handle_t	pd_kcf_prov_handle;
-	crypto_provider_id_t		pd_prov_id;
-	char				*pd_description;
-	crypto_ops_t			*pd_ops_vector;
-	uint_t				pd_mech_list_count;
-	crypto_mech_info_t		*pd_mechanisms;
-	crypto_mech_type_t		pd_map_mechnums[KCF_OPS_CLASSSIZE]\
-					    [KCF_MAXMECHTAB];
-	kcf_stats_t			*pd_stats;
-	kcf_prov_stats_t		pd_ks_data;
-	kstat_t				*pd_kstat;
-	kcf_sched_info_t		pd_sched_info;
+	crypto_session_id_t		pd_sid;
 	uint_t				pd_refcnt;
 	uint_t				pd_irefcnt;
+	kmutex_t			pd_lock;
+	kcf_prov_state_t		pd_state;
+	struct kcf_provider_list	*pd_provider_list;
+	kcondvar_t			pd_resume_cv;
+	crypto_provider_handle_t	pd_prov_handle;
+	crypto_ops_t			*pd_ops_vector;
+	ushort_t			pd_mech_indx[KCF_OPS_CLASSSIZE]\
+					    [KCF_MAXMECHTAB];
+	crypto_mech_info_t		*pd_mechanisms;
+	kcf_sched_info_t		pd_sched_info;
+	uint_t				pd_mech_list_count;
 	char				*pd_name;
 	uint_t				pd_instance;
 	int				pd_module_id;
 	struct modctl			*pd_mctlp;
-	crypto_session_id_t		pd_sid;
-	kmutex_t			pd_lock;
-	kcf_prov_state_t		pd_state;
-	kcondvar_t			pd_resume_cv;
 	kcondvar_t			pd_remove_cv;
-	boolean_t			pd_restricted;
-	struct kcf_provider_list	*pd_provider_list;
+	char				*pd_description;
 	uint_t				pd_flags;
+	crypto_kcf_provider_handle_t	pd_kcf_prov_handle;
+	crypto_provider_id_t		pd_prov_id;
+	kstat_t				*pd_kstat;
+	kcf_prov_stats_t		pd_ks_data;
 } kcf_provider_desc_t;
 
 /* useful for making a list of providers */
@@ -442,6 +437,20 @@
 
 #define	KCF_MECH2INDEX(mech_type) ((int)(mech_type))
 
+#define	KCF_TO_PROV_MECH_INDX(pd, mech_type) 			\
+	((pd)->pd_mech_indx[KCF_MECH2CLASS(mech_type)] 		\
+	[KCF_MECH2INDEX(mech_type)])
+
+#define	KCF_TO_PROV_MECHINFO(pd, mech_type)			\
+	((pd)->pd_mechanisms[KCF_TO_PROV_MECH_INDX(pd, mech_type)])
+
+#define	KCF_TO_PROV_MECHNUM(pd, mech_type)			\
+	(KCF_TO_PROV_MECHINFO(pd, mech_type).cm_mech_number)
+
+#define	KCF_CAN_SHARE_OPSTATE(pd, mech_type)			\
+	((KCF_TO_PROV_MECHINFO(pd, mech_type).cm_mech_flags) &	\
+	CRYPTO_CAN_SHARE_OPSTATE)
+
 /* ps_refcnt is protected by cm_lock in the crypto_minor structure */
 typedef struct crypto_provider_session {
 	struct crypto_provider_session *ps_next;
@@ -500,6 +509,7 @@
 #define	KCF_INVALID_MECH_NAME	0x2	/* invalid mechanism name */
 #define	KCF_INVALID_MECH_CLASS	0x3	/* invalid mechanism class */
 #define	KCF_MECH_TAB_FULL	0x4	/* Need more room in the mech tabs. */
+#define	KCF_INVALID_INDX	((ushort_t)-1)
 
 /*
  * kCF internal mechanism and function group for tracking RNG providers.
@@ -1240,7 +1250,7 @@
 int crypto_build_permitted_mech_names(kcf_provider_desc_t *,
     crypto_mech_name_t **, uint_t *, int);
 extern void kcf_init_mech_tabs(void);
-extern int kcf_add_mech_provider(crypto_mech_info_t *, kcf_provider_desc_t *,
+extern int kcf_add_mech_provider(short, kcf_provider_desc_t *,
     kcf_prov_mech_desc_t **);
 extern void kcf_remove_mech_provider(char *, kcf_provider_desc_t *);
 extern int kcf_get_mech_entry(crypto_mech_type_t, kcf_mech_entry_t **);
@@ -1274,7 +1284,7 @@
 extern void kcf_free_provider_tab(uint_t, kcf_provider_desc_t **);
 extern kcf_provider_desc_t *kcf_prov_tab_lookup(crypto_provider_id_t);
 extern int kcf_get_sw_prov(crypto_mech_type_t, kcf_provider_desc_t **,
-    boolean_t);
+    kcf_mech_entry_t **, boolean_t);
 
 /* Access to the policy table */
 extern boolean_t is_mech_disabled(kcf_provider_desc_t *, crypto_mech_name_t);
--- a/usr/src/uts/common/sys/crypto/ops_impl.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/sys/crypto/ops_impl.h	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -563,8 +563,7 @@
 
 #define	KCF_SET_PROVIDER_MECHNUM(fmtype, pd, mechp)			\
 	(mechp)->cm_type =						\
-	    (pd)->pd_map_mechnums[KCF_MECH2CLASS(fmtype)]		\
-	    [KCF_MECH2INDEX(fmtype)];
+	    KCF_TO_PROV_MECHNUM(pd, fmtype);
 
 #ifdef __cplusplus
 }
--- a/usr/src/uts/common/sys/crypto/sched_impl.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/sys/crypto/sched_impl.h	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -302,6 +302,8 @@
 	kcf_areq_node_t		*kc_req_chain_last;
 	boolean_t		kc_need_signal;	/* Initialized to B_FALSE */
 	kcf_provider_desc_t	*kc_prov_desc;	/* Prov. descriptor */
+	kcf_provider_desc_t	*kc_sw_prov_desc;	/* Prov. descriptor */
+	kcf_mech_entry_t	*kc_mech;
 	struct kcf_context	*kc_secondctx;	/* for dual contexts */
 } kcf_context_t;
 
--- a/usr/src/uts/common/sys/crypto/spi.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/common/sys/crypto/spi.h	Fri Feb 23 11:55:36 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -71,6 +71,10 @@
  */
 typedef void *crypto_req_handle_t;
 
+/* Values for cc_flags field */
+#define	CRYPTO_INIT_OPSTATE	0x00000001 /* allocate and init cc_opstate */
+#define	CRYPTO_USE_OPSTATE	0x00000002 /* .. start using it as context */
+
 /*
  * The context structure is passed from the kernel to a provider.
  * It contains the information needed to process a multi-part or
@@ -86,6 +90,8 @@
 	crypto_session_id_t	cc_session;
 	void			*cc_provider_private;	/* owned by provider */
 	void			*cc_framework_private;	/* owned by framework */
+	uint32_t		cc_flags;		/* flags */
+	void			*cc_opstate;		/* state */
 } crypto_ctx_t;
 
 /*
@@ -617,9 +623,12 @@
 	crypto_func_group_t	cm_func_group_mask;
 	ssize_t			cm_min_key_length;
 	ssize_t			cm_max_key_length;
-	crypto_keysize_unit_t	cm_keysize_unit; /* for cm_xxx_key_length */
+	uint32_t		cm_mech_flags;
 } crypto_mech_info_t;
 
+/* Alias the old name to the new name for compatibility. */
+#define	cm_keysize_unit	cm_mech_flags
+
 /*
  * crypto_kcf_provider_handle_t is a handle allocated by the kernel.
  * It is returned after the provider registers with
@@ -674,7 +683,8 @@
 
 /* hidden providers can only be accessed via a logical provider */
 #define	CRYPTO_HIDE_PROVIDER		0x00000001
-#define	CRYPTO_PIFLAGS_UNAVAILABLE	0x80000000
+#define	CRYPTO_PIFLAGS_RESERVED2	0x40000000
+#define	CRYPTO_PIFLAGS_RESERVED1	0x80000000
 
 /*
  * Provider status passed by a provider to crypto_provider_notification(9F)
--- a/usr/src/uts/sun4v/sys/n2cp.h	Fri Feb 23 09:48:45 2007 -0800
+++ b/usr/src/uts/sun4v/sys/n2cp.h	Fri Feb 23 11:55:36 2007 -0800
@@ -445,6 +445,7 @@
 	union {
 		uchar_t		val[MAXVALUE];
 		rc4_key_t	rc4val;
+		arcfour_state_t	kcf_rc4val;
 	} keystruct;
 	uint64_t	key_paddr;	/* paddr of value */
 	int		ivlen;