1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/errno.h> 31 #include <sys/types.h> 32 #include <sys/kmem.h> 33 #include <sys/cmn_err.h> 34 #include <sys/sysmacros.h> 35 #include <sys/crypto/common.h> 36 #include <sys/crypto/impl.h> 37 #include <sys/crypto/api.h> 38 #include <sys/crypto/spi.h> 39 #include <sys/crypto/sched_impl.h> 40 41 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 42 #define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f) 43 #define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f) 44 45 int 46 crypto_session_open(crypto_provider_t provider, crypto_session_id_t *sidp, 47 crypto_call_req_t *crq) 48 { 49 kcf_req_params_t params; 50 kcf_provider_desc_t *real_provider; 51 kcf_provider_desc_t *pd = provider; 52 53 ASSERT(KCF_PROV_REFHELD(pd)); 54 55 /* find a provider that supports session ops */ 56 (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops), 57 CRYPTO_SESSION_OFFSET(session_open), 58 CHECK_RESTRICT(crq), pd, &real_provider); 59 60 if (real_provider != NULL) { 61 int rv; 62 63 ASSERT(real_provider == pd || 64 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 65 66 if (CHECK_FASTPATH(crq, pd)) { 67 rv = KCF_PROV_SESSION_OPEN(real_provider, sidp, 68 KCF_SWFP_RHNDL(crq), pd); 69 KCF_PROV_INCRSTATS(pd, rv); 70 } else { 71 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 72 KCF_OP_SESSION_OPEN, sidp, 0, CRYPTO_USER, NULL, 73 0, pd); 74 rv = kcf_submit_request(real_provider, NULL, crq, 75 ¶ms, B_FALSE); 76 } 77 KCF_PROV_REFRELE(real_provider); 78 79 if (rv != CRYPTO_SUCCESS) { 80 return (rv); 81 } 82 } 83 return (CRYPTO_SUCCESS); 84 } 85 86 int 87 crypto_session_close(crypto_provider_t provider, crypto_session_id_t sid, 88 crypto_call_req_t *crq) 89 { 90 int rv; 91 kcf_req_params_t params; 92 kcf_provider_desc_t *real_provider; 93 kcf_provider_desc_t *pd = provider; 94 95 if (pd == NULL) 96 return (CRYPTO_ARGUMENTS_BAD); 97 98 ASSERT(KCF_PROV_REFHELD(pd)); 99 100 /* find a provider that supports session ops */ 101 (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops), 102 CRYPTO_SESSION_OFFSET(session_close), CHECK_RESTRICT(crq), 103 pd, &real_provider); 104 105 ASSERT(real_provider == pd || 106 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 107 108 /* edge case is where the logical provider has no members */ 109 if (real_provider != NULL) { 110 /* The fast path for SW providers. */ 111 if (CHECK_FASTPATH(crq, pd)) { 112 rv = KCF_PROV_SESSION_CLOSE(real_provider, 113 sid, KCF_SWFP_RHNDL(crq), pd); 114 KCF_PROV_INCRSTATS(pd, rv); 115 } else { 116 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 117 KCF_OP_SESSION_CLOSE, NULL, sid, 118 CRYPTO_USER, NULL, 0, pd); 119 rv = kcf_submit_request(real_provider, NULL, crq, 120 ¶ms, B_FALSE); 121 } 122 KCF_PROV_REFRELE(real_provider); 123 } 124 return (CRYPTO_SUCCESS); 125 } 126 127 int 128 crypto_session_login(crypto_provider_t provider, crypto_session_id_t sid, 129 crypto_user_type_t type, char *pin, ulong_t len, crypto_call_req_t *crq) 130 { 131 kcf_req_params_t params; 132 kcf_provider_desc_t *pd = provider; 133 kcf_provider_desc_t *real_provider = pd; 134 int rv; 135 136 ASSERT(KCF_PROV_REFHELD(pd)); 137 138 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 139 rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET( 140 session_ops), CRYPTO_SESSION_OFFSET(session_login), 141 CHECK_RESTRICT(crq), pd, &real_provider); 142 143 if (rv != CRYPTO_SUCCESS) 144 return (rv); 145 } 146 147 if (CHECK_FASTPATH(crq, real_provider)) { 148 rv = KCF_PROV_SESSION_LOGIN(real_provider, sid, 149 type, pin, len, KCF_SWFP_RHNDL(crq)); 150 KCF_PROV_INCRSTATS(pd, rv); 151 } else { 152 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, 153 NULL, sid, type, pin, len, real_provider); 154 rv = kcf_submit_request(real_provider, NULL, crq, 155 ¶ms, B_FALSE); 156 } 157 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 158 KCF_PROV_REFRELE(real_provider); 159 160 return (rv); 161 } 162 163 int 164 crypto_session_logout(crypto_provider_t provider, crypto_session_id_t sid, 165 crypto_call_req_t *crq) 166 { 167 kcf_req_params_t params; 168 kcf_provider_desc_t *pd = provider; 169 kcf_provider_desc_t *real_provider = pd; 170 int rv; 171 172 ASSERT(KCF_PROV_REFHELD(pd)); 173 174 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 175 rv = kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET( 176 session_ops), CRYPTO_SESSION_OFFSET(session_logout), 177 CHECK_RESTRICT(crq), pd, &real_provider); 178 179 if (rv != CRYPTO_SUCCESS) 180 return (rv); 181 } 182 183 if (CHECK_FASTPATH(crq, real_provider)) { 184 rv = KCF_PROV_SESSION_LOGOUT(real_provider, sid, 185 KCF_SWFP_RHNDL(crq)); 186 KCF_PROV_INCRSTATS(pd, rv); 187 } else { 188 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, 189 NULL, sid, 0, NULL, 0, real_provider); 190 rv = kcf_submit_request(real_provider, NULL, crq, 191 ¶ms, B_FALSE); 192 } 193 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 194 KCF_PROV_REFRELE(real_provider); 195 196 return (rv); 197 } 198