summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/crypto/api
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/crypto/api')
-rw-r--r--usr/src/uts/common/crypto/api/kcf_cipher.c131
-rw-r--r--usr/src/uts/common/crypto/api/kcf_digest.c80
-rw-r--r--usr/src/uts/common/crypto/api/kcf_dual.c572
-rw-r--r--usr/src/uts/common/crypto/api/kcf_keys.c243
-rw-r--r--usr/src/uts/common/crypto/api/kcf_mac.c128
-rw-r--r--usr/src/uts/common/crypto/api/kcf_miscapi.c199
-rw-r--r--usr/src/uts/common/crypto/api/kcf_object.c383
-rw-r--r--usr/src/uts/common/crypto/api/kcf_session.c197
-rw-r--r--usr/src/uts/common/crypto/api/kcf_sign.c138
-rw-r--r--usr/src/uts/common/crypto/api/kcf_verify.c145
10 files changed, 2061 insertions, 155 deletions
diff --git a/usr/src/uts/common/crypto/api/kcf_cipher.c b/usr/src/uts/common/crypto/api/kcf_cipher.c
index 5d3c8b6b57..04eb1e70fd 100644
--- a/usr/src/uts/common/crypto/api/kcf_cipher.c
+++ b/usr/src/uts/common/crypto/api/kcf_cipher.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,12 +29,16 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/kmem.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_CIPHER_OFFSET(f) offsetof(crypto_cipher_ops_t, f)
+
/*
* Encryption and decryption routines.
*/
@@ -102,7 +106,7 @@
* See comment in the beginning of the file.
*/
static int
-crypto_cipher_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_cipher_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key,
crypto_spi_ctx_template_t tmpl, crypto_context_t *ctxp,
crypto_call_req_t *crq, crypto_func_group_t func)
@@ -110,28 +114,50 @@ crypto_cipher_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
int error;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
ASSERT(KCF_PROV_REFHELD(pd));
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ if (func == CRYPTO_FG_ENCRYPT) {
+ error = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
+ CRYPTO_CIPHER_OFFSET(encrypt_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+ } else {
+ error = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
+ CRYPTO_CIPHER_OFFSET(decrypt_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+ }
+
+ if (error != CRYPTO_SUCCESS)
+ return (error);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
/* The fast path for SW providers. */
if (CHECK_FASTPATH(crq, pd)) {
crypto_mechanism_t lmech;
lmech = *mech;
- KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
+ KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
if (func == CRYPTO_FG_ENCRYPT)
- error = KCF_PROV_ENCRYPT_INIT(pd, ctx, &lmech,
- key, tmpl, KCF_SWFP_RHNDL(crq));
+ error = KCF_PROV_ENCRYPT_INIT(real_provider, ctx,
+ &lmech, key, tmpl, KCF_SWFP_RHNDL(crq));
else {
ASSERT(func == CRYPTO_FG_DECRYPT);
- error = KCF_PROV_DECRYPT_INIT(pd, ctx, &lmech,
- key, tmpl, KCF_SWFP_RHNDL(crq));
+ error = KCF_PROV_DECRYPT_INIT(real_provider, ctx,
+ &lmech, key, tmpl, KCF_SWFP_RHNDL(crq));
}
KCF_PROV_INCRSTATS(pd, error);
} else {
@@ -144,9 +170,13 @@ crypto_cipher_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
mech, key, NULL, NULL, tmpl);
}
- error = kcf_submit_request(pd, 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);
+
if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
@@ -252,17 +282,36 @@ retry:
* See comment in the beginning of the file.
*/
int
-crypto_encrypt_prov(crypto_mechanism_t *mech, crypto_data_t *plaintext,
- crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext,
- crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid)
+crypto_encrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_data_t *plaintext, crypto_key_t *key,
+ crypto_ctx_template_t tmpl, crypto_data_t *ciphertext,
+ crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int error;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ error = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
+ CRYPTO_CIPHER_OFFSET(encrypt_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (error != CRYPTO_SUCCESS)
+ return (error);
+ }
+
KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, key,
plaintext, ciphertext, tmpl);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ error = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (error);
}
/*
@@ -347,7 +396,7 @@ retry:
* Calls crypto_cipher_init_prov() to initialize an encryption operation.
*/
int
-crypto_encrypt_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_encrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key,
crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
crypto_call_req_t *crq)
@@ -405,6 +454,7 @@ crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -413,8 +463,8 @@ crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext,
ciphertext, NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE, pd->pd_sid,
- NULL, NULL, plaintext, ciphertext, NULL);
+ 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);
}
@@ -456,6 +506,7 @@ crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -463,8 +514,8 @@ crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext,
error = KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_FINAL, pd->pd_sid,
- NULL, NULL, NULL, ciphertext, NULL);
+ KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
+ ctx->cc_session, NULL, NULL, NULL, ciphertext, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
@@ -508,17 +559,36 @@ crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext,
* See comment in the beginning of the file.
*/
int
-crypto_decrypt_prov(crypto_mechanism_t *mech, crypto_data_t *ciphertext,
- crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext,
- crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid)
+crypto_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_data_t *ciphertext, crypto_key_t *key,
+ crypto_ctx_template_t tmpl, crypto_data_t *plaintext,
+ crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
+ CRYPTO_CIPHER_OFFSET(decrypt_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, key,
ciphertext, plaintext, tmpl);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
}
/*
@@ -604,7 +674,7 @@ retry:
* Calls crypto_cipher_init_prov() to initialize a decryption operation
*/
int
-crypto_decrypt_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_decrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key,
crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
crypto_call_req_t *crq)
@@ -662,6 +732,7 @@ crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -670,8 +741,8 @@ crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext,
plaintext, NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE, pd->pd_sid,
- NULL, NULL, ciphertext, plaintext, NULL);
+ 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);
}
@@ -713,15 +784,17 @@ crypto_decrypt_final(crypto_context_t context, crypto_data_t *plaintext,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
if (CHECK_FASTPATH(cr, pd)) {
- error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext, NULL);
+ error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext,
+ NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL, pd->pd_sid,
- NULL, NULL, NULL, plaintext, NULL);
+ KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
+ ctx->cc_session, NULL, NULL, NULL, plaintext, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
diff --git a/usr/src/uts/common/crypto/api/kcf_digest.c b/usr/src/uts/common/crypto/api/kcf_digest.c
index a713a473de..0058af01b4 100644
--- a/usr/src/uts/common/crypto/api/kcf_digest.c
+++ b/usr/src/uts/common/crypto/api/kcf_digest.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,12 +30,16 @@
#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_DIGEST_OFFSET(f) offsetof(crypto_digest_ops_t, f)
+
/*
* Message digest routines
*/
@@ -92,18 +96,35 @@
* See comment in the beginning of the file.
*/
int
-crypto_digest_prov(crypto_mechanism_t *mech, crypto_data_t *data,
- crypto_data_t *digest, crypto_call_req_t *crq, kcf_provider_desc_t *pd,
- crypto_session_id_t sid)
+crypto_digest_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_data_t *data, crypto_data_t *digest,
+ crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(digest_ops),
+ CRYPTO_DIGEST_OFFSET(digest_atomic), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, NULL,
data, digest);
/* no crypto context to carry between multiple parts. */
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
}
/*
@@ -184,35 +205,53 @@ retry:
* descriptor before calling this function.
*/
int
-crypto_digest_init_prov(kcf_provider_desc_t *pd,
- crypto_session_id_t sid, crypto_mechanism_t *mech,
- crypto_context_t *ctxp, crypto_call_req_t *crq)
+crypto_digest_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_context_t *ctxp, crypto_call_req_t *crq)
{
int error;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
ASSERT(KCF_PROV_REFHELD(pd));
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ error = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(digest_ops),
+ CRYPTO_DIGEST_OFFSET(digest_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (error != CRYPTO_SUCCESS)
+ return (error);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
/* The fast path for SW providers. */
if (CHECK_FASTPATH(crq, pd)) {
crypto_mechanism_t lmech;
lmech = *mech;
- KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
- error = KCF_PROV_DIGEST_INIT(pd, ctx, &lmech,
+ KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
+ error = KCF_PROV_DIGEST_INIT(real_provider, ctx, &lmech,
KCF_SWFP_RHNDL(crq));
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_INIT, sid,
mech, NULL, NULL, NULL);
- error = kcf_submit_request(pd, 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);
+
if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
@@ -295,6 +334,7 @@ crypto_digest_update(crypto_context_t context, crypto_data_t *data,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -302,8 +342,8 @@ crypto_digest_update(crypto_context_t context, crypto_data_t *data,
error = KCF_PROV_DIGEST_UPDATE(pd, ctx, data, NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_UPDATE, pd->pd_sid,
- NULL, NULL, data, NULL);
+ KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_UPDATE,
+ ctx->cc_session, NULL, NULL, data, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
@@ -345,6 +385,7 @@ crypto_digest_final(crypto_context_t context, crypto_data_t *digest,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -352,8 +393,8 @@ crypto_digest_final(crypto_context_t context, crypto_data_t *digest,
error = KCF_PROV_DIGEST_FINAL(pd, ctx, digest, NULL);
KCF_PROV_INCRSTATS(pd, error);
} else {
- KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_FINAL, pd->pd_sid,
- NULL, NULL, NULL, digest);
+ KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_FINAL,
+ ctx->cc_session, NULL, NULL, NULL, digest);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
@@ -383,6 +424,7 @@ crypto_digest_key_prov(crypto_context_t context, crypto_key_t *key,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
@@ -391,11 +433,11 @@ crypto_digest_key_prov(crypto_context_t context, crypto_key_t *key,
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_DIGEST_OPS_PARAMS(&params, KCF_OP_DIGEST_KEY,
- pd->pd_sid, NULL, key, NULL, NULL);
+ ctx->cc_session, NULL, key, NULL, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
-
KCF_PROV_REFRELE(pd);
+
return (error);
}
diff --git a/usr/src/uts/common/crypto/api/kcf_dual.c b/usr/src/uts/common/crypto/api/kcf_dual.c
index a23528e3e8..2dc8b34a66 100644
--- a/usr/src/uts/common/crypto/api/kcf_dual.c
+++ b/usr/src/uts/common/crypto/api/kcf_dual.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,18 +29,146 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/kmem.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_CIPHER_MAC_OFFSET(f) offsetof(crypto_dual_cipher_mac_ops_t, f)
static int crypto_mac_decrypt_common(crypto_mechanism_t *,
crypto_mechanism_t *, crypto_dual_data_t *, crypto_key_t *, crypto_key_t *,
crypto_ctx_template_t, crypto_ctx_template_t, crypto_data_t *,
crypto_data_t *, crypto_call_req_t *, boolean_t);
+static int crypto_mac_decrypt_common_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *, crypto_mechanism_t *,
+ crypto_dual_data_t *, crypto_key_t *, crypto_key_t *,
+ crypto_ctx_template_t, crypto_ctx_template_t, crypto_data_t *,
+ crypto_data_t *, crypto_call_req_t *, boolean_t);
+
+int
+crypto_encrypt_mac_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *encr_mech, crypto_mechanism_t *mac_mech,
+ crypto_data_t *pt, crypto_key_t *encr_key, crypto_key_t *mac_key,
+ crypto_ctx_template_t encr_tmpl, crypto_ctx_template_t mac_tmpl,
+ crypto_dual_data_t *ct, crypto_data_t *mac, crypto_call_req_t *crq)
+{
+ /*
+ * First try to find a provider for the encryption mechanism, that
+ * is also capable of the MAC mechanism.
+ */
+ int rv;
+ kcf_mech_entry_t *me;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
+ kcf_req_params_t params;
+ kcf_encrypt_mac_ops_params_t *cmops;
+ crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(encr_mech->cm_type,
+ mac_mech->cm_type, CRYPTO_OPS_OFFSET(dual_cipher_mac_ops),
+ CRYPTO_CIPHER_MAC_OFFSET(encrypt_mac_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /*
+ * For SW providers, check the validity of the context template
+ * It is very rare that the generation number mis-matches, so
+ * is acceptable to fail here, and let the consumer recover by
+ * freeing this tmpl and create a new one for the key and new SW
+ * provider
+ * Warning! will need to change when multiple software providers
+ * per mechanism are supported.
+ */
+
+ if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
+ if (encr_tmpl != NULL) {
+ if (kcf_get_mech_entry(encr_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
+ if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
+ }
+
+ if (mac_tmpl != NULL) {
+ if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
+ if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
+ }
+ }
+
+ /* The fast path for SW providers. */
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ crypto_mechanism_t lencr_mech;
+ crypto_mechanism_t lmac_mech;
+
+ /* careful! structs assignments */
+ lencr_mech = *encr_mech;
+ KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
+ &lencr_mech);
+
+ lmac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &lmac_mech);
+
+ rv = KCF_PROV_ENCRYPT_MAC_ATOMIC(real_provider, sid,
+ &lencr_mech, encr_key, &lmac_mech, mac_key, pt, ct,
+ mac, spi_encr_tmpl, spi_mac_tmpl, KCF_SWFP_RHNDL(crq));
+
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_ATOMIC,
+ sid, encr_key, mac_key, pt, ct, mac, spi_encr_tmpl,
+ spi_mac_tmpl);
+
+ cmops = &(params.rp_u.encrypt_mac_params);
+
+ /* careful! structs assignments */
+ cmops->em_encr_mech = *encr_mech;
+ KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
+ &cmops->em_encr_mech);
+ cmops->em_framework_encr_mechtype = encr_mech->cm_type;
+
+ cmops->em_mac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &cmops->em_mac_mech);
+ cmops->em_framework_mac_mechtype = mac_mech->cm_type;
+
+ rv = kcf_submit_request(real_provider, NULL, crq, &params,
+ B_FALSE);
+ }
+
+out:
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+ return (rv);
+}
+
/*
* Performs a dual encrypt/mac atomic operation. The provider and session
* to use are determined by the KCF dispatcher.
@@ -286,6 +414,140 @@ retry:
return (error);
}
+int
+crypto_encrypt_mac_init_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *encr_mech,
+ crypto_mechanism_t *mac_mech, crypto_key_t *encr_key,
+ crypto_key_t *mac_key, crypto_ctx_template_t encr_tmpl,
+ crypto_ctx_template_t mac_tmpl, crypto_context_t *ctxp,
+ crypto_call_req_t *cr)
+{
+ /*
+ * First try to find a provider for the encryption mechanism, that
+ * is also capable of the MAC mechanism.
+ */
+ int rv;
+ kcf_mech_entry_t *me;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ kcf_ctx_template_t *ctx_encr_tmpl, *ctx_mac_tmpl;
+ kcf_req_params_t params;
+ kcf_encrypt_mac_ops_params_t *cmops;
+ crypto_spi_ctx_template_t spi_encr_tmpl = NULL, spi_mac_tmpl = NULL;
+ crypto_ctx_t *ctx;
+ kcf_context_t *encr_kcf_context = NULL;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(encr_mech->cm_type,
+ mac_mech->cm_type, CRYPTO_OPS_OFFSET(dual_cipher_mac_ops),
+ CRYPTO_CIPHER_MAC_OFFSET(encrypt_mac_init),
+ CHECK_RESTRICT(cr), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /*
+ * For SW providers, check the validity of the context template
+ * It is very rare that the generation number mis-matches, so
+ * is acceptable to fail here, and let the consumer recover by
+ * freeing this tmpl and create a new one for the key and new SW
+ * provider
+ * Warning! will need to change when multiple software providers
+ * per mechanism are supported.
+ */
+
+ if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
+ if (encr_tmpl != NULL) {
+ if (kcf_get_mech_entry(encr_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_encr_tmpl = (kcf_ctx_template_t *)encr_tmpl;
+ if (ctx_encr_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_encr_tmpl = ctx_encr_tmpl->ct_prov_tmpl;
+ }
+
+ if (mac_tmpl != NULL) {
+ if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
+ if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
+ }
+ }
+
+ ctx = kcf_new_ctx(cr, real_provider, sid);
+ if (ctx == NULL) {
+ rv = CRYPTO_HOST_MEMORY;
+ goto out;
+ }
+ encr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
+
+ /* The fast path for SW providers. */
+ if (CHECK_FASTPATH(cr, real_provider)) {
+ crypto_mechanism_t lencr_mech;
+ crypto_mechanism_t lmac_mech;
+
+ /* careful! structs assignments */
+ lencr_mech = *encr_mech;
+ KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
+ &lencr_mech);
+
+ lmac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &lmac_mech);
+
+ rv = KCF_PROV_ENCRYPT_MAC_INIT(real_provider, ctx, &lencr_mech,
+ encr_key, &lmac_mech, mac_key, spi_encr_tmpl, spi_mac_tmpl,
+ KCF_SWFP_RHNDL(cr));
+
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_INIT,
+ sid, encr_key, mac_key, NULL, NULL, NULL,
+ spi_encr_tmpl, spi_mac_tmpl);
+
+ cmops = &(params.rp_u.encrypt_mac_params);
+
+ /* careful! structs assignments */
+ cmops->em_encr_mech = *encr_mech;
+ KCF_SET_PROVIDER_MECHNUM(encr_mech->cm_type, real_provider,
+ &cmops->em_encr_mech);
+ cmops->em_framework_encr_mechtype = encr_mech->cm_type;
+
+ cmops->em_mac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &cmops->em_mac_mech);
+ cmops->em_framework_mac_mechtype = mac_mech->cm_type;
+
+ rv = kcf_submit_request(real_provider, ctx, cr, &params,
+ B_FALSE);
+ }
+
+ if (rv != CRYPTO_SUCCESS && rv != CRYPTO_QUEUED) {
+ KCF_CONTEXT_REFRELE(encr_kcf_context);
+ } else
+ *ctxp = (crypto_context_t)ctx;
+
+out:
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+ return (rv);
+}
+
/*
* Starts a multi-part dual encrypt/mac operation. The provider and session
* to use are determined by the KCF dispatcher.
@@ -622,6 +884,7 @@ crypto_encrypt_mac_update(crypto_context_t context,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
@@ -698,7 +961,7 @@ crypto_encrypt_mac_update(crypto_context_t context,
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
- pd->pd_sid, NULL, NULL, pt, ct, NULL, NULL, NULL);
+ ctx->cc_session, NULL, NULL, pt, ct, NULL, NULL, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
@@ -726,6 +989,7 @@ int crypto_encrypt_mac_final(crypto_context_t context, crypto_dual_data_t *ct,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
@@ -800,7 +1064,7 @@ int crypto_encrypt_mac_final(crypto_context_t context, crypto_dual_data_t *ct,
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_ENCRYPT_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
- pd->pd_sid, NULL, NULL, NULL, ct, mac, NULL, NULL);
+ ctx->cc_session, NULL, NULL, NULL, ct, mac, NULL, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
out:
@@ -825,6 +1089,18 @@ crypto_mac_decrypt(crypto_mechanism_t *mac_mech,
decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_FALSE));
}
+int
+crypto_mac_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mac_mech, crypto_mechanism_t *decr_mech,
+ crypto_dual_data_t *ct, crypto_key_t *mac_key, crypto_key_t *decr_key,
+ crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
+ crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
+{
+ return (crypto_mac_decrypt_common_prov(provider, sid, mac_mech,
+ decr_mech, ct, mac_key, decr_key, mac_tmpl, decr_tmpl, mac, pt,
+ crq, B_FALSE));
+}
+
/*
* Performs an atomic dual mac/decrypt operation. The provider to use
* is determined by the KCF dispatcher. 'mac' specifies the expected
@@ -842,6 +1118,19 @@ crypto_mac_verify_decrypt(crypto_mechanism_t *mac_mech,
decr_key, mac_tmpl, decr_tmpl, mac, pt, crq, B_TRUE));
}
+int
+crypto_mac_verify_decrypt_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
+ crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
+ crypto_key_t *mac_key, crypto_key_t *decr_key,
+ crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
+ crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq)
+{
+ return (crypto_mac_decrypt_common_prov(provider, sid, mac_mech,
+ decr_mech, ct, mac_key, decr_key, mac_tmpl, decr_tmpl, mac, pt,
+ crq, B_TRUE));
+}
+
/*
* Called by both crypto_mac_decrypt() and crypto_mac_verify_decrypt().
* optionally verified if the MACs match before calling the decryption step.
@@ -1108,6 +1397,143 @@ retry:
return (error);
}
+static int
+crypto_mac_decrypt_common_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
+ crypto_mechanism_t *decr_mech, crypto_dual_data_t *ct,
+ crypto_key_t *mac_key, crypto_key_t *decr_key,
+ crypto_ctx_template_t mac_tmpl, crypto_ctx_template_t decr_tmpl,
+ crypto_data_t *mac, crypto_data_t *pt, crypto_call_req_t *crq,
+ boolean_t do_verify)
+{
+ /*
+ * First try to find a provider for the decryption mechanism, that
+ * is also capable of the MAC mechanism.
+ * We still favor optimizing the costlier decryption.
+ */
+ int error;
+ kcf_mech_entry_t *me;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
+ kcf_req_params_t params;
+ kcf_mac_decrypt_ops_params_t *cmops;
+ crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ if (do_verify) {
+ error = kcf_get_hardware_provider(decr_mech->cm_type,
+ mac_mech->cm_type,
+ CRYPTO_OPS_OFFSET(dual_cipher_mac_ops),
+ CRYPTO_CIPHER_MAC_OFFSET(mac_verify_decrypt_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+ } else {
+ error = kcf_get_hardware_provider(decr_mech->cm_type,
+ mac_mech->cm_type,
+ CRYPTO_OPS_OFFSET(dual_cipher_mac_ops),
+ CRYPTO_CIPHER_MAC_OFFSET(mac_decrypt_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+ }
+
+ if (error != CRYPTO_SUCCESS)
+ return (error);
+ }
+
+ /*
+ * For SW providers, check the validity of the context template
+ * It is very rare that the generation number mis-matches, so
+ * is acceptable to fail here, and let the consumer recover by
+ * freeing this tmpl and create a new one for the key and new SW
+ * provider
+ */
+
+ if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
+ if (decr_tmpl != NULL) {
+ if (kcf_get_mech_entry(decr_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ error = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
+ if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
+ error = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
+ }
+
+ if (mac_tmpl != NULL) {
+ if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ error = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
+ if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
+ error = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
+ }
+ }
+
+ /* The fast path for SW providers. */
+ if (CHECK_FASTPATH(crq, pd)) {
+ crypto_mechanism_t lmac_mech;
+ crypto_mechanism_t ldecr_mech;
+
+ /* careful! structs assignments */
+ ldecr_mech = *decr_mech;
+ KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
+ &ldecr_mech);
+
+ lmac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &lmac_mech);
+
+ if (do_verify)
+ error = KCF_PROV_MAC_VERIFY_DECRYPT_ATOMIC(
+ real_provider, sid, &lmac_mech, mac_key,
+ &ldecr_mech, decr_key, ct, mac, pt, spi_mac_tmpl,
+ spi_decr_tmpl, KCF_SWFP_RHNDL(crq));
+ else
+ error = KCF_PROV_MAC_DECRYPT_ATOMIC(real_provider, sid,
+ &lmac_mech, mac_key, &ldecr_mech, decr_key,
+ ct, mac, pt, spi_mac_tmpl, spi_decr_tmpl,
+ KCF_SWFP_RHNDL(crq));
+
+ KCF_PROV_INCRSTATS(pd, error);
+ } else {
+ KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params,
+ (do_verify) ? KCF_OP_MAC_VERIFY_DECRYPT_ATOMIC :
+ KCF_OP_ATOMIC, sid, mac_key, decr_key, ct, mac, pt,
+ spi_mac_tmpl, spi_decr_tmpl);
+
+ cmops = &(params.rp_u.mac_decrypt_params);
+
+ /* careful! structs assignments */
+ cmops->md_decr_mech = *decr_mech;
+ KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
+ &cmops->md_decr_mech);
+ cmops->md_framework_decr_mechtype = decr_mech->cm_type;
+
+ cmops->md_mac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &cmops->md_mac_mech);
+ cmops->md_framework_mac_mechtype = mac_mech->cm_type;
+
+ error = kcf_submit_request(real_provider, NULL, crq, &params,
+ B_FALSE);
+ }
+
+out:
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+ return (error);
+}
+
/*
* Starts a multi-part dual mac/decrypt operation. The provider to
* use is determined by the KCF dispatcher.
@@ -1429,6 +1855,140 @@ retry:
return (error);
}
+int
+crypto_mac_decrypt_init_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *mac_mech,
+ crypto_mechanism_t *decr_mech, crypto_key_t *mac_key,
+ crypto_key_t *decr_key, crypto_ctx_template_t mac_tmpl,
+ crypto_ctx_template_t decr_tmpl, crypto_context_t *ctxp,
+ crypto_call_req_t *cr)
+{
+ /*
+ * First try to find a provider for the decryption mechanism, that
+ * is also capable of the MAC mechanism.
+ * We still favor optimizing the costlier decryption.
+ */
+ int rv;
+ kcf_mech_entry_t *me;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ kcf_ctx_template_t *ctx_decr_tmpl, *ctx_mac_tmpl;
+ kcf_req_params_t params;
+ kcf_mac_decrypt_ops_params_t *mdops;
+ crypto_spi_ctx_template_t spi_decr_tmpl = NULL, spi_mac_tmpl = NULL;
+ crypto_ctx_t *ctx;
+ kcf_context_t *decr_kcf_context = NULL;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(decr_mech->cm_type,
+ mac_mech->cm_type, CRYPTO_OPS_OFFSET(dual_cipher_mac_ops),
+ CRYPTO_CIPHER_MAC_OFFSET(mac_decrypt_init),
+ CHECK_RESTRICT(cr), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /*
+ * For SW providers, check the validity of the context template
+ * It is very rare that the generation number mis-matches, so
+ * is acceptable to fail here, and let the consumer recover by
+ * freeing this tmpl and create a new one for the key and new SW
+ * provider
+ * Warning! will need to change when multiple software providers
+ * per mechanism are supported.
+ */
+
+ if (real_provider->pd_prov_type == CRYPTO_SW_PROVIDER) {
+ if (decr_tmpl != NULL) {
+ if (kcf_get_mech_entry(decr_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_decr_tmpl = (kcf_ctx_template_t *)decr_tmpl;
+ if (ctx_decr_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_decr_tmpl = ctx_decr_tmpl->ct_prov_tmpl;
+ }
+
+ if (mac_tmpl != NULL) {
+ if (kcf_get_mech_entry(mac_mech->cm_type, &me) !=
+ KCF_SUCCESS) {
+ rv = CRYPTO_MECHANISM_INVALID;
+ goto out;
+ }
+ ctx_mac_tmpl = (kcf_ctx_template_t *)mac_tmpl;
+ if (ctx_mac_tmpl->ct_generation != me->me_gen_swprov) {
+ rv = CRYPTO_OLD_CTX_TEMPLATE;
+ goto out;
+ }
+ spi_mac_tmpl = ctx_mac_tmpl->ct_prov_tmpl;
+ }
+ }
+
+ ctx = kcf_new_ctx(cr, real_provider, sid);
+ if (ctx == NULL) {
+ rv = CRYPTO_HOST_MEMORY;
+ goto out;
+ }
+ decr_kcf_context = (kcf_context_t *)ctx->cc_framework_private;
+
+ /* The fast path for SW providers. */
+ if (CHECK_FASTPATH(cr, pd)) {
+ crypto_mechanism_t ldecr_mech;
+ crypto_mechanism_t lmac_mech;
+
+ /* careful! structs assignments */
+ ldecr_mech = *decr_mech;
+ KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
+ &ldecr_mech);
+
+ lmac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &lmac_mech);
+
+ rv = KCF_PROV_MAC_DECRYPT_INIT(real_provider, ctx, &lmac_mech,
+ mac_key, &ldecr_mech, decr_key, spi_mac_tmpl, spi_decr_tmpl,
+ KCF_SWFP_RHNDL(cr));
+
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT,
+ sid, mac_key, decr_key, NULL, NULL, NULL,
+ spi_mac_tmpl, spi_decr_tmpl);
+
+ mdops = &(params.rp_u.mac_decrypt_params);
+
+ /* careful! structs assignments */
+ mdops->md_decr_mech = *decr_mech;
+ KCF_SET_PROVIDER_MECHNUM(decr_mech->cm_type, real_provider,
+ &mdops->md_decr_mech);
+ mdops->md_framework_decr_mechtype = decr_mech->cm_type;
+
+ mdops->md_mac_mech = *mac_mech;
+ KCF_SET_PROVIDER_MECHNUM(mac_mech->cm_type, real_provider,
+ &mdops->md_mac_mech);
+ mdops->md_framework_mac_mechtype = mac_mech->cm_type;
+
+ rv = kcf_submit_request(real_provider, ctx, cr, &params,
+ B_FALSE);
+ }
+
+ if (rv != CRYPTO_SUCCESS && rv != CRYPTO_QUEUED) {
+ KCF_CONTEXT_REFRELE(decr_kcf_context);
+ } else
+ *ctxp = (crypto_context_t)ctx;
+
+out:
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+ return (rv);
+}
/*
* Continues a multi-part dual mac/decrypt operation.
*/
@@ -1449,6 +2009,7 @@ crypto_mac_decrypt_update(crypto_context_t context,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
@@ -1511,7 +2072,7 @@ crypto_mac_decrypt_update(crypto_context_t context,
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
- pd->pd_sid, NULL, NULL, ct, NULL, pt, NULL, NULL);
+ ctx->cc_session, NULL, NULL, ct, NULL, pt, NULL, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
@@ -1540,6 +2101,7 @@ crypto_mac_decrypt_final(crypto_context_t context, crypto_data_t *mac,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
if ((kcf_mac_ctx = kcf_ctx->kc_secondctx) != NULL) {
@@ -1589,7 +2151,7 @@ crypto_mac_decrypt_final(crypto_context_t context, crypto_data_t *mac,
KCF_PROV_INCRSTATS(pd, error);
} else {
KCF_WRAP_MAC_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
- pd->pd_sid, NULL, NULL, NULL, mac, pt, NULL, NULL);
+ ctx->cc_session, NULL, NULL, NULL, mac, pt, NULL, NULL);
error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
diff --git a/usr/src/uts/common/crypto/api/kcf_keys.c b/usr/src/uts/common/crypto/api/kcf_keys.c
new file mode 100644
index 0000000000..c95fd9f72d
--- /dev/null
+++ b/usr/src/uts/common/crypto/api/kcf_keys.c
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
+#include <sys/crypto/common.h>
+#include <sys/crypto/impl.h>
+#include <sys/crypto/api.h>
+#include <sys/crypto/spi.h>
+#include <sys/crypto/sched_impl.h>
+
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f)
+
+int
+crypto_key_generate(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_object_attribute_t *attrs, uint_t count,
+ crypto_object_id_t *handle, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_generate), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_KEY_GENERATE(real_provider, sid,
+ mech, attrs, count, handle, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE, sid,
+ mech, attrs, count, handle, NULL, 0, NULL, NULL, NULL, 0);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_key_generate_pair(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_object_attribute_t *pub_attrs,
+ uint_t pub_count, crypto_object_attribute_t *pri_attrs, uint_t pri_count,
+ crypto_object_id_t *pub_handle, crypto_object_id_t *pri_handle,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_generate_pair), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_KEY_GENERATE_PAIR(real_provider, sid, mech,
+ pub_attrs, pub_count, pri_attrs, pri_count, pub_handle,
+ pri_handle, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_GENERATE_PAIR,
+ sid, mech, pub_attrs, pub_count, pub_handle, pri_attrs,
+ pri_count, pri_handle, NULL, NULL, 0);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_key_wrap(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *wrapping_key,
+ crypto_object_id_t *key, uchar_t *wrapped_key, size_t *wrapped_key_len,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_wrap), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_KEY_WRAP(real_provider, sid, mech, wrapping_key,
+ key, wrapped_key, wrapped_key_len, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_WRAP, sid, mech,
+ NULL, 0, key, NULL, 0, NULL, wrapping_key, wrapped_key,
+ wrapped_key_len);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_key_unwrap(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *unwrapping_key,
+ uchar_t *wrapped_key, size_t *wrapped_key_len,
+ crypto_object_attribute_t *attrs, uint_t count, crypto_object_id_t *key,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_unwrap), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_KEY_UNWRAP(real_provider, sid, mech,
+ unwrapping_key, wrapped_key, wrapped_key_len, attrs,
+ count, key, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_UNWRAP, sid, mech,
+ attrs, count, key, NULL, 0, NULL, unwrapping_key,
+ wrapped_key, wrapped_key_len);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_key_derive(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *base_key,
+ crypto_object_attribute_t *attrs, uint_t count,
+ crypto_object_id_t *new_key, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_derive), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_KEY_DERIVE(real_provider, sid, mech, base_key,
+ attrs, count, new_key, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_KEY_OPS_PARAMS(&params, KCF_OP_KEY_DERIVE, sid, mech,
+ attrs, count, new_key, NULL, 0, NULL, base_key, NULL, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
diff --git a/usr/src/uts/common/crypto/api/kcf_mac.c b/usr/src/uts/common/crypto/api/kcf_mac.c
index a0459bcc50..57b2a7595f 100644
--- a/usr/src/uts/common/crypto/api/kcf_mac.c
+++ b/usr/src/uts/common/crypto/api/kcf_mac.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,12 +29,16 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/kmem.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_MAC_OFFSET(f) offsetof(crypto_mac_ops_t, f)
+
/*
* Message authentication codes routines.
*/
@@ -92,17 +96,34 @@
* See comment in the beginning of the file.
*/
int
-crypto_mac_prov(crypto_mechanism_t *mech, crypto_data_t *data,
- crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac,
- crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid)
+crypto_mac_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key,
+ crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops),
+ CRYPTO_MAC_OFFSET(mac_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, key,
data, mac, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
/*
@@ -189,17 +210,34 @@ retry:
* The other arguments are the same as the function crypto_mac_prov().
*/
int
-crypto_mac_verify_prov(crypto_mechanism_t *mech, crypto_data_t *data,
- crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac,
- crypto_call_req_t *crq, kcf_provider_desc_t *pd, crypto_session_id_t sid)
+crypto_mac_verify_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key,
+ crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops),
+ CRYPTO_MAC_OFFSET(mac_verify_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech,
key, data, mac, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
/*
@@ -318,43 +356,62 @@ retry:
* See comment in the beginning of the file.
*/
int
-crypto_mac_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_mac_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl,
crypto_context_t *ctxp, crypto_call_req_t *crq)
{
- int error;
+ int rv;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
ASSERT(KCF_PROV_REFHELD(pd));
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops),
+ CRYPTO_MAC_OFFSET(mac_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
/* The fast path for SW providers. */
if (CHECK_FASTPATH(crq, pd)) {
crypto_mechanism_t lmech;
lmech = *mech;
- KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
- error = KCF_PROV_MAC_INIT(pd, ctx, &lmech, key, tmpl,
+ KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
+ rv = KCF_PROV_MAC_INIT(real_provider, ctx, &lmech, key, tmpl,
KCF_SWFP_RHNDL(crq));
- KCF_PROV_INCRSTATS(pd, error);
+ KCF_PROV_INCRSTATS(pd, rv);
} else {
KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_INIT, sid, mech, key,
NULL, NULL, tmpl);
- error = kcf_submit_request(pd, ctx, crq, &params, B_FALSE);
+ rv = kcf_submit_request(real_provider, ctx, crq, &params,
+ B_FALSE);
}
- if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
/* Release the hold done in kcf_new_ctx(). */
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
}
- return (error);
+ return (rv);
}
/*
@@ -444,9 +501,8 @@ crypto_mac_update(crypto_context_t context, crypto_data_t *data,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
kcf_req_params_t params;
-
+ int rv;
if ((ctx == NULL) ||
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
@@ -454,20 +510,21 @@ crypto_mac_update(crypto_context_t context, crypto_data_t *data,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
if (CHECK_FASTPATH(cr, pd)) {
- error = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL);
- KCF_PROV_INCRSTATS(pd, error);
+ rv = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL);
+ KCF_PROV_INCRSTATS(pd, rv);
} else {
- KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE, pd->pd_sid,
- NULL, NULL, data, NULL, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_UPDATE,
+ ctx->cc_session, NULL, NULL, data, NULL, NULL);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
KCF_PROV_REFRELE(pd);
- return (error);
+ return (rv);
}
/*
@@ -495,8 +552,8 @@ crypto_mac_final(crypto_context_t context, crypto_data_t *mac,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
kcf_req_params_t params;
+ int rv;
if ((ctx == NULL) ||
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
@@ -504,22 +561,23 @@ crypto_mac_final(crypto_context_t context, crypto_data_t *mac,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
/* The fast path for SW providers. */
if (CHECK_FASTPATH(cr, pd)) {
- error = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL);
- KCF_PROV_INCRSTATS(pd, error);
+ rv = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL);
+ KCF_PROV_INCRSTATS(pd, rv);
} else {
- KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_FINAL, pd->pd_sid, NULL,
- NULL, NULL, mac, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ KCF_WRAP_MAC_OPS_PARAMS(&params, KCF_OP_FINAL,
+ ctx->cc_session, NULL, NULL, NULL, mac, NULL);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
}
KCF_PROV_REFRELE(pd);
/* Release the hold done in kcf_new_ctx() during init step. */
- KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
- return (error);
+ KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx);
+ return (rv);
}
/*
diff --git a/usr/src/uts/common/crypto/api/kcf_miscapi.c b/usr/src/uts/common/crypto/api/kcf_miscapi.c
index e86c27fe1f..6242df6dc8 100644
--- a/usr/src/uts/common/crypto/api/kcf_miscapi.c
+++ b/usr/src/uts/common/crypto/api/kcf_miscapi.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,11 +30,20 @@
#include <sys/sunddi.h>
#include <sys/disp.h>
#include <sys/modctl.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/api.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/sched_impl.h>
+#define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
+ ((ch) == '\t') || ((ch) == '\f'))
+
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f)
+#define CRYPTO_PROVIDER_OFFSET(f) \
+ offsetof(crypto_provider_management_ops_t, f)
+
/* Miscellaneous exported entry points */
/*
@@ -571,6 +580,40 @@ crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key)
return (CRYPTO_SUCCESS);
}
+int
+crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech,
+ crypto_key_t *key)
+{
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ crypto_mechanism_t lmech;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if ((mech == NULL) || (key == NULL) ||
+ (key->ck_format == CRYPTO_KEY_REFERENCE))
+ return (CRYPTO_ARGUMENTS_BAD);
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(key_ops),
+ CRYPTO_KEY_OFFSET(key_check), CHECK_RESTRICT_FALSE,
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ lmech = *mech;
+ KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
+ rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
/*
* Initialize the specified crypto_mechanism_info_t structure for
* the specified mechanism provider descriptor. Used by
@@ -662,3 +705,157 @@ bail:
*num_mech_infos = ninfos;
return (rv);
}
+
+/*
+ * memcmp_pad_max() is a specialized version of memcmp() which
+ * compares two pieces of data up to a maximum length. If the
+ * the two data match up the maximum length, they are considered
+ * matching. Trailing blanks do not cause the match to fail if
+ * one of the data is shorter.
+ *
+ * Examples of matches:
+ * "one" |
+ * "one " |
+ * ^maximum length
+ *
+ * "Number One | X" (X is beyond maximum length)
+ * "Number One " |
+ * ^maximum length
+ *
+ * Examples of mismatches:
+ * " one"
+ * "one"
+ *
+ * "Number One X|"
+ * "Number One |"
+ * ^maximum length
+ */
+static int
+memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
+{
+ uint_t len, extra_len;
+ char *marker;
+
+ /* No point in comparing anything beyond max_sz */
+ if (d1_len > max_sz)
+ d1_len = max_sz;
+ if (d2_len > max_sz)
+ d2_len = max_sz;
+
+ /* Find shorter of the two data. */
+ if (d1_len <= d2_len) {
+ len = d1_len;
+ extra_len = d2_len;
+ marker = d2;
+ } else { /* d1_len > d2_len */
+ len = d2_len;
+ extra_len = d1_len;
+ marker = d1;
+ }
+
+ /* Have a match in the shortest length of data? */
+ if (memcmp(d1, d2, len) != 0)
+ /* CONSTCOND */
+ return (!0);
+
+ /* If the rest of longer data is nulls or blanks, call it a match. */
+ while (len < extra_len)
+ if (!isspace(marker[len++]))
+ /* CONSTCOND */
+ return (!0);
+ return (0);
+}
+
+/*
+ * Obtain ext info for specified provider and see if it matches.
+ */
+static boolean_t
+match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial,
+ crypto_provider_ext_info_t *ext_info)
+{
+ kcf_provider_desc_t *real_provider;
+ int rv;
+ kcf_req_params_t params;
+
+ (void) kcf_get_hardware_provider_nomech(
+ CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
+ CHECK_RESTRICT_FALSE, pd, &real_provider);
+
+ if (real_provider != NULL) {
+ ASSERT(real_provider == pd ||
+ pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
+ KCF_WRAP_PROVMGMT_OPS_PARAMS(&params, KCF_OP_MGMT_EXTINFO,
+ 0, NULL, 0, NULL, 0, NULL, ext_info, pd);
+ rv = kcf_submit_request(real_provider, NULL, NULL, &params,
+ B_FALSE);
+ ASSERT(rv != CRYPTO_NOT_SUPPORTED);
+ KCF_PROV_REFRELE(real_provider);
+ }
+
+ if (rv != CRYPTO_SUCCESS)
+ return (B_FALSE);
+
+ if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL,
+ label, strlen(label), CRYPTO_EXT_SIZE_LABEL))
+ return (B_FALSE);
+
+ if (manuf != NULL) {
+ if (memcmp_pad_max(ext_info->ei_manufacturerID,
+ CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf),
+ CRYPTO_EXT_SIZE_MANUF))
+ return (B_FALSE);
+ }
+
+ if (serial != NULL) {
+ if (memcmp_pad_max(ext_info->ei_serial_number,
+ CRYPTO_EXT_SIZE_SERIAL, label, strlen(label),
+ CRYPTO_EXT_SIZE_SERIAL))
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+/*
+ * Find a provider based on its label, manufacturer ID, and serial number.
+ */
+crypto_provider_t
+crypto_get_provider(char *label, char *manuf, char *serial)
+{
+ kcf_provider_desc_t **provider_array, *pd;
+ crypto_provider_ext_info_t *ext_info;
+ uint_t count;
+ int i;
+
+ /* manuf and serial are optional */
+ if (label == NULL)
+ return (NULL);
+
+ if (kcf_get_slot_list(&count, &provider_array, B_FALSE)
+ != CRYPTO_SUCCESS)
+ return (NULL);
+
+ if (count == 0)
+ return (NULL);
+
+ ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP);
+
+ for (i = 0; i < count; i++) {
+ pd = provider_array[i];
+ if (match_ext_info(pd, label, manuf, serial, ext_info)) {
+ KCF_PROV_REFHOLD(pd);
+ break;
+ }
+ }
+ if (i == count)
+ pd = NULL;
+
+ kcf_free_provider_tab(count, provider_array);
+ kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
+ return (pd);
+}
+
+void
+crypto_release_provider(crypto_provider_t provider)
+{
+ KCF_PROV_REFRELE((kcf_provider_desc_t *)provider);
+}
diff --git a/usr/src/uts/common/crypto/api/kcf_object.c b/usr/src/uts/common/crypto/api/kcf_object.c
new file mode 100644
index 0000000000..148ed9a817
--- /dev/null
+++ b/usr/src/uts/common/crypto/api/kcf_object.c
@@ -0,0 +1,383 @@
+/*
+ * 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.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
+#include <sys/crypto/common.h>
+#include <sys/crypto/impl.h>
+#include <sys/crypto/api.h>
+#include <sys/crypto/spi.h>
+#include <sys/crypto/sched_impl.h>
+
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f)
+
+int
+crypto_object_create(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_object_attribute_t *attrs, uint_t count,
+ crypto_object_id_t *object_handle, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_create),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_CREATE(real_provider, sid,
+ attrs, count, object_handle, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_CREATE,
+ sid, 0, attrs, count, object_handle, 0,
+ NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_destroy(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_object_id_t object_handle, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_destroy),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_DESTROY(real_provider, sid,
+ object_handle, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_DESTROY,
+ sid, object_handle, NULL, 0, NULL, 0,
+ NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_copy(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_object_id_t object_handle, crypto_object_attribute_t *attrs,
+ uint_t count, crypto_object_id_t *new_handle, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_copy),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_COPY(real_provider, sid,
+ object_handle, attrs, count, new_handle,
+ KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_COPY,
+ sid, object_handle, attrs, count,
+ new_handle, 0, NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_get_attribute_value(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_object_id_t object_handle,
+ crypto_object_attribute_t *attrs, uint_t count, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops),
+ CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_GET_ATTRIBUTE_VALUE(real_provider,
+ sid, object_handle, attrs, count, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params,
+ KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE, sid, object_handle,
+ attrs, count, NULL, 0, NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_set_attribute_value(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_object_id_t object_handle,
+ crypto_object_attribute_t *attrs, uint_t count, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops),
+ CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_SET_ATTRIBUTE_VALUE(real_provider,
+ sid, object_handle, attrs, count, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params,
+ KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE, sid, object_handle,
+ attrs, count, NULL, 0, NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_get_size(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_object_id_t object_handle, size_t *size, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_get_size),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_GET_SIZE(real_provider,
+ sid, object_handle, size, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_GET_SIZE, sid,
+ object_handle, NULL, 0, NULL, size, NULL, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_find_init(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_object_attribute_t *attrs, uint_t count, void **cookie,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (cookie == NULL) {
+ return (CRYPTO_ARGUMENTS_BAD);
+ }
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_find_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_FIND_INIT(real_provider,
+ sid, attrs, count, cookie, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_INIT,
+ sid, 0, attrs, count, NULL, 0, cookie, NULL, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_find_final(crypto_provider_t provider, void *cookie,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_find_final),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_FIND_FINAL(real_provider,
+ cookie, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND_FINAL,
+ 0, 0, NULL, 0, NULL, 0, NULL, cookie, 0, NULL);
+ rv = kcf_submit_request(real_provider, NULL, NULL, &params,
+ B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_object_find(crypto_provider_t provider, void *cookie,
+ crypto_object_id_t *handles, uint_t *count, uint_t max_count,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ object_ops), CRYPTO_OBJECT_OFFSET(object_find),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_OBJECT_FIND(real_provider, cookie, handles,
+ max_count, count, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_OBJECT_OPS_PARAMS(&params, KCF_OP_OBJECT_FIND, 0,
+ 0, NULL, 0, handles, 0, NULL, cookie, max_count, count);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
diff --git a/usr/src/uts/common/crypto/api/kcf_session.c b/usr/src/uts/common/crypto/api/kcf_session.c
new file mode 100644
index 0000000000..b887829ea3
--- /dev/null
+++ b/usr/src/uts/common/crypto/api/kcf_session.c
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
+#include <sys/crypto/common.h>
+#include <sys/crypto/impl.h>
+#include <sys/crypto/api.h>
+#include <sys/crypto/spi.h>
+#include <sys/crypto/sched_impl.h>
+
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f)
+#define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f)
+
+int
+crypto_session_open(crypto_provider_t provider, crypto_session_id_t *sidp,
+crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *real_provider;
+ kcf_provider_desc_t *pd = provider;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ /* find a provider that supports session ops */
+ (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
+ CRYPTO_SESSION_OFFSET(session_open),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (real_provider != NULL) {
+ int rv;
+
+ ASSERT(real_provider == pd ||
+ pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
+
+ if (CHECK_FASTPATH(crq, pd)) {
+ rv = KCF_PROV_SESSION_OPEN(real_provider, sidp,
+ KCF_SWFP_RHNDL(crq), pd);
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_SESSION_OPS_PARAMS(&params,
+ KCF_OP_SESSION_OPEN, sidp, 0, CRYPTO_USER, NULL,
+ 0, pd);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ KCF_PROV_REFRELE(real_provider);
+
+ if (rv != CRYPTO_SUCCESS) {
+ return (rv);
+ }
+ }
+ return (CRYPTO_SUCCESS);
+}
+
+int
+crypto_session_close(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_call_req_t *crq)
+{
+ int rv;
+ kcf_req_params_t params;
+ kcf_provider_desc_t *real_provider;
+ kcf_provider_desc_t *pd = provider;
+
+ if (pd == NULL)
+ return (CRYPTO_ARGUMENTS_BAD);
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ /* find a provider that supports session ops */
+ (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
+ CRYPTO_SESSION_OFFSET(session_close), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ ASSERT(real_provider == pd ||
+ pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
+
+ /* edge case is where the logical provider has no members */
+ if (real_provider != NULL) {
+ /* The fast path for SW providers. */
+ if (CHECK_FASTPATH(crq, pd)) {
+ rv = KCF_PROV_SESSION_CLOSE(real_provider,
+ sid, KCF_SWFP_RHNDL(crq), pd);
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_SESSION_OPS_PARAMS(&params,
+ KCF_OP_SESSION_CLOSE, NULL, sid,
+ CRYPTO_USER, NULL, 0, pd);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ KCF_PROV_REFRELE(real_provider);
+ }
+ return (CRYPTO_SUCCESS);
+}
+
+int
+crypto_session_login(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_user_type_t type, char *pin, ulong_t len, crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ session_ops), CRYPTO_SESSION_OFFSET(session_login),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_SESSION_LOGIN(real_provider, sid,
+ type, pin, len, KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGIN,
+ NULL, sid, type, pin, len, real_provider);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
+
+int
+crypto_session_logout(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_call_req_t *crq)
+{
+ kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(
+ session_ops), CRYPTO_SESSION_OFFSET(session_logout),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ if (CHECK_FASTPATH(crq, real_provider)) {
+ rv = KCF_PROV_SESSION_LOGOUT(real_provider, sid,
+ KCF_SWFP_RHNDL(crq));
+ KCF_PROV_INCRSTATS(pd, rv);
+ } else {
+ KCF_WRAP_SESSION_OPS_PARAMS(&params, KCF_OP_SESSION_LOGOUT,
+ NULL, sid, 0, NULL, 0, real_provider);
+ rv = kcf_submit_request(real_provider, NULL, crq,
+ &params, B_FALSE);
+ }
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
+
+ return (rv);
+}
diff --git a/usr/src/uts/common/crypto/api/kcf_sign.c b/usr/src/uts/common/crypto/api/kcf_sign.c
index b4a052563f..c098f0ca10 100644
--- a/usr/src/uts/common/crypto/api/kcf_sign.c
+++ b/usr/src/uts/common/crypto/api/kcf_sign.c
@@ -29,12 +29,16 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/kmem.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_SIGN_OFFSET(f) offsetof(crypto_sign_ops_t, f)
+
/*
* Sign entry points.
*/
@@ -43,30 +47,49 @@
* See comments for crypto_digest_init_prov().
*/
int
-crypto_sign_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_sign_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key, crypto_ctx_template_t tmpl,
crypto_context_t *ctxp, crypto_call_req_t *crq)
{
- int error;
+ int rv;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(sign_ops),
+ CRYPTO_SIGN_OFFSET(sign_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_INIT, sid, mech,
key, NULL, NULL, tmpl);
+ rv = kcf_submit_request(real_provider, ctx, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- error = kcf_submit_request(pd, ctx, crq, &params, B_FALSE);
- if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
+ if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
/* Release the hold done in kcf_new_ctx(). */
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
}
- return (error);
+ return (rv);
}
int
@@ -161,8 +184,8 @@ crypto_sign_update(crypto_context_t context, crypto_data_t *data,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
kcf_req_params_t params;
+ int rv;
if ((ctx == NULL) ||
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
@@ -170,13 +193,14 @@ crypto_sign_update(crypto_context_t context, crypto_data_t *data,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
- KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_UPDATE, 0, NULL,
+ KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_UPDATE, ctx->cc_session, NULL,
NULL, data, NULL, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
KCF_PROV_REFRELE(pd);
- return (error);
+ return (rv);
}
/*
@@ -189,7 +213,7 @@ crypto_sign_final(crypto_context_t context, crypto_data_t *signature,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
+ int rv;
kcf_req_params_t params;
if ((ctx == NULL) ||
@@ -198,30 +222,47 @@ crypto_sign_final(crypto_context_t context, crypto_data_t *signature,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
- KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_FINAL, 0, NULL,
+ KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_FINAL, ctx->cc_session, NULL,
NULL, NULL, signature, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
KCF_PROV_REFRELE(pd);
/* Release the hold done in kcf_new_ctx() during init step. */
- KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
- return (error);
+ KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx);
+ return (rv);
}
int
-crypto_sign_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_sign_prov(crypto_provider_t provider, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data,
crypto_ctx_template_t tmpl, crypto_data_t *signature,
crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(sign_ops),
+ CRYPTO_SIGN_OFFSET(sign_atomic), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech,
key, data, signature, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
static int
@@ -315,18 +356,34 @@ crypto_sign(crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data,
}
int
-crypto_sign_recover_prov(kcf_provider_desc_t *pd,
- crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key,
- crypto_data_t *data, crypto_ctx_template_t tmpl, crypto_data_t *signature,
+crypto_sign_recover_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data,
+ crypto_ctx_template_t tmpl, crypto_data_t *signature,
crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(sign_ops),
+ CRYPTO_SIGN_OFFSET(sign_recover_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_SIGN_RECOVER_ATOMIC, sid, mech,
key, data, signature, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
int
@@ -339,30 +396,49 @@ crypto_sign_recover(crypto_mechanism_t *mech, crypto_key_t *key,
}
int
-crypto_sign_recover_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
- crypto_mechanism_t *mech, crypto_key_t *key, crypto_ctx_template_t tmpl,
- crypto_context_t *ctxp, crypto_call_req_t *crq)
+crypto_sign_recover_init_prov(crypto_provider_t provider,
+ crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key,
+ crypto_ctx_template_t tmpl, crypto_context_t *ctxp, crypto_call_req_t *crq)
{
- int error;
+ int rv;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(sign_ops),
+ CRYPTO_SIGN_OFFSET(sign_recover_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
KCF_WRAP_SIGN_OPS_PARAMS(&params, KCF_OP_SIGN_RECOVER_INIT, sid, mech,
key, NULL, NULL, tmpl);
+ rv = kcf_submit_request(real_provider, ctx, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- error = kcf_submit_request(pd, ctx, crq, &params, B_FALSE);
- if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
+ if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
/* Release the hold done in kcf_new_ctx(). */
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
}
- return (error);
+ return (rv);
}
int
diff --git a/usr/src/uts/common/crypto/api/kcf_verify.c b/usr/src/uts/common/crypto/api/kcf_verify.c
index 0ca0f376e0..dee7197df2 100644
--- a/usr/src/uts/common/crypto/api/kcf_verify.c
+++ b/usr/src/uts/common/crypto/api/kcf_verify.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,12 +29,16 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/kmem.h>
+#include <sys/sysmacros.h>
#include <sys/crypto/common.h>
#include <sys/crypto/impl.h>
#include <sys/crypto/api.h>
#include <sys/crypto/spi.h>
#include <sys/crypto/sched_impl.h>
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_VERIFY_OFFSET(f) offsetof(crypto_verify_ops_t, f)
+
/*
* Verify entry points.
*/
@@ -43,30 +47,49 @@
* See comments for crypto_digest_init_prov().
*/
int
-crypto_verify_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid,
+crypto_verify_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
crypto_mechanism_t *mech, crypto_key_t *key, crypto_ctx_template_t tmpl,
crypto_context_t *ctxp, crypto_call_req_t *crq)
{
- int error;
+ int rv;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(verify_ops),
+ CRYPTO_VERIFY_OFFSET(verify_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_INIT, sid, mech,
key, NULL, NULL, tmpl);
+ rv = kcf_submit_request(real_provider, ctx, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- error = kcf_submit_request(pd, ctx, crq, &params, B_FALSE);
- if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
+ if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
/* Release the hold done in kcf_new_ctx(). */
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
}
- return (error);
+ return (rv);
}
@@ -163,8 +186,8 @@ crypto_verify_update(crypto_context_t context, crypto_data_t *data,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
kcf_req_params_t params;
+ int rv;
if ((ctx == NULL) ||
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
@@ -172,13 +195,14 @@ crypto_verify_update(crypto_context_t context, crypto_data_t *data,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
- KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_UPDATE, 0, NULL,
- NULL, data, NULL, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_UPDATE, ctx->cc_session,
+ NULL, NULL, data, NULL, NULL);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
KCF_PROV_REFRELE(pd);
- return (error);
+ return (rv);
}
/*
@@ -191,8 +215,8 @@ crypto_verify_final(crypto_context_t context, crypto_data_t *signature,
crypto_ctx_t *ctx = (crypto_ctx_t *)context;
kcf_context_t *kcf_ctx;
kcf_provider_desc_t *pd;
- int error;
kcf_req_params_t params;
+ int rv;
if ((ctx == NULL) ||
((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
@@ -200,30 +224,47 @@ crypto_verify_final(crypto_context_t context, crypto_data_t *signature,
return (CRYPTO_INVALID_CONTEXT);
}
+ ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
KCF_PROV_REFHOLD(pd);
- KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_FINAL, 0, NULL,
- NULL, NULL, signature, NULL);
- error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
+ KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_FINAL, ctx->cc_session,
+ NULL, NULL, NULL, signature, NULL);
+ rv = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
KCF_PROV_REFRELE(pd);
/* Release the hold done in kcf_new_ctx() during init step. */
- KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
- return (error);
+ KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx);
+ return (rv);
}
int
-crypto_verify_prov(kcf_provider_desc_t *pd,
- crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key,
- crypto_data_t *data, crypto_ctx_template_t tmpl, crypto_data_t *signature,
+crypto_verify_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data,
+ crypto_ctx_template_t tmpl, crypto_data_t *signature,
crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(verify_ops),
+ CRYPTO_VERIFY_OFFSET(verify_atomic), CHECK_RESTRICT(crq),
+ pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech,
key, data, signature, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
static int
@@ -318,18 +359,33 @@ crypto_verify(crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data,
}
int
-crypto_verify_recover_prov(kcf_provider_desc_t *pd,
- crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key,
- crypto_data_t *signature, crypto_ctx_template_t tmpl, crypto_data_t *data,
- crypto_call_req_t *crq)
+crypto_verify_recover_prov(crypto_provider_t provider, crypto_session_id_t sid,
+ crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *signature,
+ crypto_ctx_template_t tmpl, crypto_data_t *data, crypto_call_req_t *crq)
{
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+ int rv;
ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(verify_ops),
+ CRYPTO_VERIFY_OFFSET(verify_recover_atomic),
+ CHECK_RESTRICT(crq), pd, &real_provider);
+
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_VERIFY_RECOVER_ATOMIC,
sid, mech, key, data, signature, tmpl);
+ rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- return (kcf_submit_request(pd, NULL, crq, &params, B_FALSE));
+ return (rv);
}
int
@@ -342,30 +398,49 @@ crypto_verify_recover(crypto_mechanism_t *mech, crypto_key_t *key,
}
int
-crypto_verify_recover_init_prov(kcf_provider_desc_t *pd,
+crypto_verify_recover_init_prov(crypto_provider_t provider,
crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key,
crypto_ctx_template_t tmpl, crypto_context_t *ctxp, crypto_call_req_t *crq)
{
- int error;
+ int rv;
crypto_ctx_t *ctx;
kcf_req_params_t params;
+ kcf_provider_desc_t *pd = provider;
+ kcf_provider_desc_t *real_provider = pd;
+
+ ASSERT(KCF_PROV_REFHELD(pd));
+
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
+ rv = kcf_get_hardware_provider(mech->cm_type,
+ CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(verify_ops),
+ CRYPTO_VERIFY_OFFSET(verify_recover_init),
+ CHECK_RESTRICT(crq), pd, &real_provider);
- /* First, allocate and initialize the canonical context */
- if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL)
+ if (rv != CRYPTO_SUCCESS)
+ return (rv);
+ }
+
+ /* Allocate and initialize the canonical context */
+ if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
return (CRYPTO_HOST_MEMORY);
+ }
KCF_WRAP_VERIFY_OPS_PARAMS(&params, KCF_OP_VERIFY_RECOVER_INIT,
sid, mech, key, NULL, NULL, tmpl);
+ rv = kcf_submit_request(real_provider, ctx, crq, &params, B_FALSE);
+ if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
+ KCF_PROV_REFRELE(real_provider);
- error = kcf_submit_request(pd, ctx, crq, &params, B_FALSE);
- if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
+ if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED))
*ctxp = (crypto_context_t)ctx;
else {
/* Release the hold done in kcf_new_ctx(). */
KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
}
- return (error);
+ return (rv);
}
int