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