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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 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_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f) 39 40 int 41 crypto_key_generate(crypto_provider_t provider, crypto_session_id_t sid, 42 crypto_mechanism_t *mech, crypto_object_attribute_t *attrs, uint_t count, 43 crypto_object_id_t *handle, crypto_call_req_t *crq) 44 { 45 kcf_req_params_t params; 46 kcf_provider_desc_t *pd = provider; 47 kcf_provider_desc_t *real_provider = pd; 48 int rv; 49 50 ASSERT(KCF_PROV_REFHELD(pd)); 51 52 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 53 rv = kcf_get_hardware_provider(mech->cm_type, NULL, 54 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT(crq), 55 pd, &real_provider, CRYPTO_FG_GENERATE); 56 57 if (rv != CRYPTO_SUCCESS) 58 return (rv); 59 } 60 61 if (CHECK_FASTPATH(crq, real_provider)) { 62 rv = KCF_PROV_KEY_GENERATE(real_provider, sid, 63 mech, attrs, count, handle, KCF_SWFP_RHNDL(crq)); 64 KCF_PROV_INCRSTATS(pd, rv); 65 } else { 66 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE, sid, 67 mech, attrs, count, handle, NULL, 0, NULL, NULL, NULL, 0); 68 rv = kcf_submit_request(real_provider, NULL, crq, 69 ¶ms, B_FALSE); 70 } 71 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 72 KCF_PROV_REFRELE(real_provider); 73 74 return (rv); 75 } 76 77 int 78 crypto_key_generate_pair(crypto_provider_t provider, crypto_session_id_t sid, 79 crypto_mechanism_t *mech, crypto_object_attribute_t *pub_attrs, 80 uint_t pub_count, crypto_object_attribute_t *pri_attrs, uint_t pri_count, 81 crypto_object_id_t *pub_handle, crypto_object_id_t *pri_handle, 82 crypto_call_req_t *crq) 83 { 84 kcf_req_params_t params; 85 kcf_provider_desc_t *pd = provider; 86 kcf_provider_desc_t *real_provider = pd; 87 int rv; 88 89 ASSERT(KCF_PROV_REFHELD(pd)); 90 91 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 92 rv = kcf_get_hardware_provider(mech->cm_type, NULL, 93 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT(crq), 94 pd, &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR); 95 96 if (rv != CRYPTO_SUCCESS) 97 return (rv); 98 } 99 100 if (CHECK_FASTPATH(crq, real_provider)) { 101 rv = KCF_PROV_KEY_GENERATE_PAIR(real_provider, sid, mech, 102 pub_attrs, pub_count, pri_attrs, pri_count, pub_handle, 103 pri_handle, KCF_SWFP_RHNDL(crq)); 104 KCF_PROV_INCRSTATS(pd, rv); 105 } else { 106 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR, 107 sid, mech, pub_attrs, pub_count, pub_handle, pri_attrs, 108 pri_count, pri_handle, NULL, NULL, 0); 109 rv = kcf_submit_request(real_provider, NULL, crq, 110 ¶ms, B_FALSE); 111 } 112 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 113 KCF_PROV_REFRELE(real_provider); 114 115 return (rv); 116 } 117 118 int 119 crypto_key_wrap(crypto_provider_t provider, crypto_session_id_t sid, 120 crypto_mechanism_t *mech, crypto_key_t *wrapping_key, 121 crypto_object_id_t *key, uchar_t *wrapped_key, size_t *wrapped_key_len, 122 crypto_call_req_t *crq) 123 { 124 kcf_req_params_t params; 125 kcf_provider_desc_t *pd = provider; 126 kcf_provider_desc_t *real_provider = pd; 127 int rv; 128 129 ASSERT(KCF_PROV_REFHELD(pd)); 130 131 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 132 rv = kcf_get_hardware_provider(mech->cm_type, wrapping_key, 133 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT(crq), 134 pd, &real_provider, CRYPTO_FG_WRAP); 135 136 if (rv != CRYPTO_SUCCESS) 137 return (rv); 138 } 139 140 if (CHECK_FASTPATH(crq, real_provider)) { 141 rv = KCF_PROV_KEY_WRAP(real_provider, sid, mech, wrapping_key, 142 key, wrapped_key, wrapped_key_len, KCF_SWFP_RHNDL(crq)); 143 KCF_PROV_INCRSTATS(pd, rv); 144 } else { 145 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP, sid, mech, 146 NULL, 0, key, NULL, 0, NULL, wrapping_key, wrapped_key, 147 wrapped_key_len); 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_key_unwrap(crypto_provider_t provider, crypto_session_id_t sid, 159 crypto_mechanism_t *mech, crypto_key_t *unwrapping_key, 160 uchar_t *wrapped_key, size_t *wrapped_key_len, 161 crypto_object_attribute_t *attrs, uint_t count, crypto_object_id_t *key, 162 crypto_call_req_t *crq) 163 { 164 kcf_req_params_t params; 165 kcf_provider_desc_t *pd = provider; 166 kcf_provider_desc_t *real_provider = pd; 167 int rv; 168 169 ASSERT(KCF_PROV_REFHELD(pd)); 170 171 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 172 rv = kcf_get_hardware_provider(mech->cm_type, unwrapping_key, 173 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT(crq), 174 pd, &real_provider, CRYPTO_FG_UNWRAP); 175 176 if (rv != CRYPTO_SUCCESS) 177 return (rv); 178 } 179 180 if (CHECK_FASTPATH(crq, real_provider)) { 181 rv = KCF_PROV_KEY_UNWRAP(real_provider, sid, mech, 182 unwrapping_key, wrapped_key, wrapped_key_len, attrs, 183 count, key, KCF_SWFP_RHNDL(crq)); 184 KCF_PROV_INCRSTATS(pd, rv); 185 } else { 186 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP, sid, mech, 187 attrs, count, key, NULL, 0, NULL, unwrapping_key, 188 wrapped_key, wrapped_key_len); 189 rv = kcf_submit_request(real_provider, NULL, crq, 190 ¶ms, B_FALSE); 191 } 192 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 193 KCF_PROV_REFRELE(real_provider); 194 195 return (rv); 196 } 197 198 int 199 crypto_key_derive(crypto_provider_t provider, crypto_session_id_t sid, 200 crypto_mechanism_t *mech, crypto_key_t *base_key, 201 crypto_object_attribute_t *attrs, uint_t count, 202 crypto_object_id_t *new_key, crypto_call_req_t *crq) 203 { 204 kcf_req_params_t params; 205 kcf_provider_desc_t *pd = provider; 206 kcf_provider_desc_t *real_provider = pd; 207 int rv; 208 209 ASSERT(KCF_PROV_REFHELD(pd)); 210 211 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 212 rv = kcf_get_hardware_provider(mech->cm_type, base_key, 213 CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT(crq), 214 pd, &real_provider, CRYPTO_FG_DERIVE); 215 216 if (rv != CRYPTO_SUCCESS) 217 return (rv); 218 } 219 220 if (CHECK_FASTPATH(crq, real_provider)) { 221 rv = KCF_PROV_KEY_DERIVE(real_provider, sid, mech, base_key, 222 attrs, count, new_key, KCF_SWFP_RHNDL(crq)); 223 KCF_PROV_INCRSTATS(pd, rv); 224 } else { 225 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE, sid, mech, 226 attrs, count, new_key, NULL, 0, NULL, base_key, NULL, NULL); 227 rv = kcf_submit_request(real_provider, NULL, crq, 228 ¶ms, B_FALSE); 229 } 230 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 231 KCF_PROV_REFRELE(real_provider); 232 233 return (rv); 234 } 235