diff options
Diffstat (limited to 'usr/src/uts/common/crypto/api')
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_cipher.c | 131 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_digest.c | 80 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_dual.c | 572 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_keys.c | 243 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_mac.c | 128 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_miscapi.c | 199 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_object.c | 383 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_session.c | 197 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_sign.c | 138 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/api/kcf_verify.c | 145 |
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, ¶ms, B_FALSE); + error = kcf_submit_request(real_provider, ctx, crq, ¶ms, + 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(¶ms, KCF_OP_ATOMIC, sid, mech, key, plaintext, ciphertext, tmpl); - return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); + error = kcf_submit_request(real_provider, NULL, crq, ¶ms, 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(¶ms, KCF_OP_UPDATE, pd->pd_sid, - NULL, NULL, plaintext, ciphertext, NULL); + KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, + ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, pd->pd_sid, - NULL, NULL, NULL, ciphertext, NULL); + KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, + ctx->cc_session, NULL, NULL, NULL, ciphertext, NULL); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_ATOMIC, sid, mech, key, ciphertext, plaintext, tmpl); - return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, 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(¶ms, KCF_OP_UPDATE, pd->pd_sid, - NULL, NULL, ciphertext, plaintext, NULL); + KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_UPDATE, + ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, pd->pd_sid, - NULL, NULL, NULL, plaintext, NULL); + KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms, KCF_OP_FINAL, + ctx->cc_session, NULL, NULL, NULL, plaintext, NULL); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_ATOMIC, sid, mech, NULL, data, digest); /* no crypto context to carry between multiple parts. */ - return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, 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(¶ms, KCF_OP_INIT, sid, mech, NULL, NULL, NULL); - error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); + error = kcf_submit_request(real_provider, ctx, crq, ¶ms, + 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(¶ms, KCF_OP_UPDATE, pd->pd_sid, - NULL, NULL, data, NULL); + KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_UPDATE, + ctx->cc_session, NULL, NULL, data, NULL); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, pd->pd_sid, - NULL, NULL, NULL, digest); + KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_FINAL, + ctx->cc_session, NULL, NULL, NULL, digest); error = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, 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, ¶ms, 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(¶ms, 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, ¶ms, + 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(¶ms, 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, ¶ms, + 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(¶ms, 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, ¶ms, 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(¶ms, 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, ¶ms, 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(¶ms, + (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, ¶ms, + 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(¶ms, 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, ¶ms, + 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(¶ms, 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, ¶ms, 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(¶ms, 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, ¶ms, 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(¶ms, KCF_OP_KEY_GENERATE, sid, + mech, attrs, count, handle, NULL, 0, NULL, NULL, NULL, 0); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, 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, + ¶ms, 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(¶ms, 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, + ¶ms, 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(¶ms, 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, + ¶ms, 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(¶ms, 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, + ¶ms, 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(¶ms, KCF_OP_ATOMIC, sid, mech, key, data, mac, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech, key, data, mac, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_INIT, sid, mech, key, NULL, NULL, tmpl); - error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); + rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, + 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(¶ms, KCF_OP_UPDATE, pd->pd_sid, - NULL, NULL, data, NULL, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_UPDATE, + ctx->cc_session, NULL, NULL, data, NULL, NULL); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, pd->pd_sid, NULL, - NULL, NULL, mac, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_FINAL, + ctx->cc_session, NULL, NULL, NULL, mac, NULL); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_MGMT_EXTINFO, + 0, NULL, 0, NULL, 0, NULL, ext_info, pd); + rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, + 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(¶ms, KCF_OP_OBJECT_CREATE, + sid, 0, attrs, count, object_handle, 0, + NULL, NULL, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_OBJECT_DESTROY, + sid, object_handle, NULL, 0, NULL, 0, + NULL, NULL, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_OBJECT_COPY, + sid, object_handle, attrs, count, + new_handle, 0, NULL, NULL, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, + 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, + ¶ms, 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(¶ms, + 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, + ¶ms, 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(¶ms, KCF_OP_OBJECT_GET_SIZE, sid, + object_handle, NULL, 0, NULL, size, NULL, NULL, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_OBJECT_FIND_INIT, + sid, 0, attrs, count, NULL, 0, cookie, NULL, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_OBJECT_FIND_FINAL, + 0, 0, NULL, 0, NULL, 0, NULL, cookie, 0, NULL); + rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, + 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(¶ms, KCF_OP_OBJECT_FIND, 0, + 0, NULL, 0, handles, 0, NULL, cookie, max_count, count); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, + KCF_OP_SESSION_OPEN, sidp, 0, CRYPTO_USER, NULL, + 0, pd); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, + KCF_OP_SESSION_CLOSE, NULL, sid, + CRYPTO_USER, NULL, 0, pd); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_SESSION_LOGIN, + NULL, sid, type, pin, len, real_provider); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_SESSION_LOGOUT, + NULL, sid, 0, NULL, 0, real_provider); + rv = kcf_submit_request(real_provider, NULL, crq, + ¶ms, 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(¶ms, KCF_OP_INIT, sid, mech, key, NULL, NULL, tmpl); + rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - error = kcf_submit_request(pd, ctx, crq, ¶ms, 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(¶ms, KCF_OP_UPDATE, 0, NULL, + KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_UPDATE, ctx->cc_session, NULL, NULL, data, NULL, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, 0, NULL, + KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_FINAL, ctx->cc_session, NULL, NULL, NULL, signature, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_ATOMIC, sid, mech, key, data, signature, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_SIGN_RECOVER_ATOMIC, sid, mech, key, data, signature, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_SIGN_RECOVER_INIT, sid, mech, key, NULL, NULL, tmpl); + rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - error = kcf_submit_request(pd, ctx, crq, ¶ms, 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(¶ms, KCF_OP_INIT, sid, mech, key, NULL, NULL, tmpl); + rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - error = kcf_submit_request(pd, ctx, crq, ¶ms, 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(¶ms, KCF_OP_UPDATE, 0, NULL, - NULL, data, NULL, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + KCF_WRAP_VERIFY_OPS_PARAMS(¶ms, KCF_OP_UPDATE, ctx->cc_session, + NULL, NULL, data, NULL, NULL); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_FINAL, 0, NULL, - NULL, NULL, signature, NULL); - error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); + KCF_WRAP_VERIFY_OPS_PARAMS(¶ms, KCF_OP_FINAL, ctx->cc_session, + NULL, NULL, NULL, signature, NULL); + rv = kcf_submit_request(pd, ctx, cr, ¶ms, 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(¶ms, KCF_OP_ATOMIC, sid, mech, key, data, signature, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_VERIFY_RECOVER_ATOMIC, sid, mech, key, data, signature, tmpl); + rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - return (kcf_submit_request(pd, NULL, crq, ¶ms, 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(¶ms, KCF_OP_VERIFY_RECOVER_INIT, sid, mech, key, NULL, NULL, tmpl); + rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, B_FALSE); + if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) + KCF_PROV_REFRELE(real_provider); - error = kcf_submit_request(pd, ctx, crq, ¶ms, 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 |
