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