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) 2003, 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_DIGEST_OFFSET(f) offsetof(crypto_digest_ops_t, f) 38 39 /* 40 * Message digest routines 41 */ 42 43 /* 44 * The following are the possible returned values common to all the routines 45 * below. The applicability of some of these return values depends on the 46 * presence of the arguments. 47 * 48 * CRYPTO_SUCCESS: The operation completed successfully. 49 * CRYPTO_QUEUED: A request was submitted successfully. The callback 50 * routine will be called when the operation is done. 51 * CRYPTO_MECHANISM_INVALID or CRYPTO_INVALID_MECH_PARAM 52 * for problems with the 'mech'. 53 * CRYPTO_INVALID_DATA for bogus 'data' 54 * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work. 55 * CRYPTO_INVALID_CONTEXT: Not a valid context. 56 * CRYPTO_BUSY: Cannot process the request now. Schedule a 57 * crypto_bufcall(), or try later. 58 * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: 59 * No provider is capable of a function or a mechanism. 60 */ 61 62 63 /* 64 * crypto_digest_prov() 65 * 66 * Arguments: 67 * pd: pointer to the descriptor of the provider to use for this 68 * operation. 69 * sid: provider session id. 70 * mech: crypto_mechanism_t pointer. 71 * mech_type is a valid value previously returned by 72 * crypto_mech2id(); 73 * When the mech's parameter is not NULL, its definition depends 74 * on the standard definition of the mechanism. 75 * data: The message to be digested. 76 * digest: Storage for the digest. The length needed depends on the 77 * mechanism. 78 * cr: crypto_call_req_t calling conditions and call back info. 79 * 80 * Description: 81 * Asynchronously submits a request for, or synchronously performs the 82 * digesting operation of 'data' on the specified 83 * provider with the specified session. 84 * When complete and successful, 'digest' will contain the digest value. 85 * The caller should hold a reference on the specified provider 86 * descriptor before calling this function. 87 * 88 * Context: 89 * Process or interrupt, according to the semantics dictated by the 'cr'. 90 * 91 * Returns: 92 * See comment in the beginning of the file. 93 */ 94 int 95 crypto_digest_prov(crypto_provider_t provider, crypto_session_id_t sid, 96 crypto_mechanism_t *mech, crypto_data_t *data, crypto_data_t *digest, 97 crypto_call_req_t *crq) 98 { 99 kcf_req_params_t params; 100 kcf_provider_desc_t *pd = provider; 101 kcf_provider_desc_t *real_provider = pd; 102 int rv; 103 104 ASSERT(KCF_PROV_REFHELD(pd)); 105 106 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 107 rv = kcf_get_hardware_provider(mech->cm_type, NULL, 108 CRYPTO_MECH_INVALID, NULL, pd, &real_provider, 109 CRYPTO_FG_DIGEST_ATOMIC); 110 111 if (rv != CRYPTO_SUCCESS) 112 return (rv); 113 } 114 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, NULL, 115 data, digest); 116 117 /* no crypto context to carry between multiple parts. */ 118 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 119 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 120 KCF_PROV_REFRELE(real_provider); 121 122 return (rv); 123 } 124 125 /* 126 * Same as crypto_digest_prov(), but relies on the KCF scheduler to 127 * choose a provider. See crypto_digest_prov() comments for more information. 128 */ 129 int 130 crypto_digest(crypto_mechanism_t *mech, crypto_data_t *data, 131 crypto_data_t *digest, crypto_call_req_t *crq) 132 { 133 int error; 134 kcf_provider_desc_t *pd; 135 kcf_req_params_t params; 136 kcf_prov_tried_t *list = NULL; 137 138 retry: 139 /* The pd is returned held */ 140 if ((pd = kcf_get_mech_provider(mech->cm_type, NULL, NULL, &error, 141 list, CRYPTO_FG_DIGEST_ATOMIC, data->cd_length)) == NULL) { 142 if (list != NULL) 143 kcf_free_triedlist(list); 144 return (error); 145 } 146 147 /* The fast path for SW providers. */ 148 if (CHECK_FASTPATH(crq, pd)) { 149 crypto_mechanism_t lmech; 150 151 lmech = *mech; 152 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 153 error = KCF_PROV_DIGEST_ATOMIC(pd, pd->pd_sid, &lmech, data, 154 digest, KCF_SWFP_RHNDL(crq)); 155 KCF_PROV_INCRSTATS(pd, error); 156 } else { 157 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 158 (pd->pd_flags & CRYPTO_HASH_NO_UPDATE) && 159 (data->cd_length > pd->pd_hash_limit)) { 160 error = CRYPTO_BUFFER_TOO_BIG; 161 } else { 162 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, 163 pd->pd_sid, mech, NULL, data, digest); 164 165 /* no crypto context to carry between multiple parts. */ 166 error = kcf_submit_request(pd, NULL, crq, ¶ms, 167 B_FALSE); 168 } 169 } 170 171 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 172 IS_RECOVERABLE(error)) { 173 /* Add pd to the linked list of providers tried. */ 174 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 175 goto retry; 176 } 177 178 if (list != NULL) 179 kcf_free_triedlist(list); 180 181 KCF_PROV_REFRELE(pd); 182 return (error); 183 } 184 185 /* 186 * crypto_digest_init_prov() 187 * 188 * pd: pointer to the descriptor of the provider to use for this 189 * operation. 190 * sid: provider session id. 191 * mech: crypto_mechanism_t pointer. 192 * mech_type is a valid value previously returned by 193 * crypto_mech2id(); 194 * When the mech's parameter is not NULL, its definition depends 195 * on the standard definition of the mechanism. 196 * ctxp: Pointer to a crypto_context_t. 197 * cr: crypto_call_req_t calling conditions and call back info. 198 * 199 * Description: 200 * Asynchronously submits a request for, or synchronously performs the 201 * initialization of a message digest operation on the specified 202 * provider with the specified session. 203 * When complete and successful, 'ctxp' will contain a crypto_context_t 204 * valid for later calls to digest_update() and digest_final(). 205 * The caller should hold a reference on the specified provider 206 * descriptor before calling this function. 207 */ 208 int 209 crypto_digest_init_prov(crypto_provider_t provider, crypto_session_id_t sid, 210 crypto_mechanism_t *mech, crypto_context_t *ctxp, crypto_call_req_t *crq) 211 { 212 int error; 213 crypto_ctx_t *ctx; 214 kcf_req_params_t params; 215 kcf_provider_desc_t *pd = provider; 216 kcf_provider_desc_t *real_provider = pd; 217 218 ASSERT(KCF_PROV_REFHELD(pd)); 219 220 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 221 error = kcf_get_hardware_provider(mech->cm_type, NULL, 222 CRYPTO_MECH_INVALID, NULL, pd, &real_provider, 223 CRYPTO_FG_DIGEST); 224 225 if (error != CRYPTO_SUCCESS) 226 return (error); 227 } 228 229 /* Allocate and initialize the canonical context */ 230 if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) { 231 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 232 KCF_PROV_REFRELE(real_provider); 233 return (CRYPTO_HOST_MEMORY); 234 } 235 236 /* The fast path for SW providers. */ 237 if (CHECK_FASTPATH(crq, pd)) { 238 crypto_mechanism_t lmech; 239 240 lmech = *mech; 241 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 242 error = KCF_PROV_DIGEST_INIT(real_provider, ctx, &lmech, 243 KCF_SWFP_RHNDL(crq)); 244 KCF_PROV_INCRSTATS(pd, error); 245 } else { 246 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, 247 mech, NULL, NULL, NULL); 248 error = kcf_submit_request(real_provider, ctx, crq, ¶ms, 249 B_FALSE); 250 } 251 252 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 253 KCF_PROV_REFRELE(real_provider); 254 255 if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 256 *ctxp = (crypto_context_t)ctx; 257 else { 258 /* Release the hold done in kcf_new_ctx(). */ 259 KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 260 } 261 262 return (error); 263 } 264 265 266 /* 267 * Same as crypto_digest_init_prov(), but relies on the KCF scheduler 268 * to choose a provider. See crypto_digest_init_prov() comments for 269 * more information. 270 */ 271 int 272 crypto_digest_init(crypto_mechanism_t *mech, crypto_context_t *ctxp, 273 crypto_call_req_t *crq) 274 { 275 int error; 276 kcf_provider_desc_t *pd; 277 kcf_prov_tried_t *list = NULL; 278 279 retry: 280 /* The pd is returned held */ 281 if ((pd = kcf_get_mech_provider(mech->cm_type, NULL, NULL, &error, 282 list, CRYPTO_FG_DIGEST, 0)) == NULL) { 283 if (list != NULL) 284 kcf_free_triedlist(list); 285 return (error); 286 } 287 288 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 289 (pd->pd_flags & CRYPTO_HASH_NO_UPDATE)) { 290 /* 291 * The hardware provider has limited digest support. 292 * So, we fallback early here to using a software provider. 293 * 294 * XXX - need to enhance to do the fallback later in 295 * crypto_digest_update() if the size of accumulated input data 296 * exceeds the maximum size digestable by hardware provider. 297 */ 298 error = CRYPTO_BUFFER_TOO_BIG; 299 } else { 300 error = crypto_digest_init_prov(pd, pd->pd_sid, 301 mech, ctxp, crq); 302 } 303 304 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 305 IS_RECOVERABLE(error)) { 306 /* Add pd to the linked list of providers tried. */ 307 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 308 goto retry; 309 } 310 311 if (list != NULL) 312 kcf_free_triedlist(list); 313 KCF_PROV_REFRELE(pd); 314 return (error); 315 } 316 317 /* 318 * crypto_digest_update() 319 * 320 * Arguments: 321 * context: A crypto_context_t initialized by digest_init(). 322 * data: The part of message to be digested. 323 * cr: crypto_call_req_t calling conditions and call back info. 324 * 325 * Description: 326 * Asynchronously submits a request for, or synchronously performs a 327 * part of a message digest operation. 328 * 329 * Context: 330 * Process or interrupt, according to the semantics dictated by the 'cr'. 331 * 332 * Returns: 333 * See comment in the beginning of the file. 334 */ 335 int 336 crypto_digest_update(crypto_context_t context, crypto_data_t *data, 337 crypto_call_req_t *cr) 338 { 339 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 340 kcf_context_t *kcf_ctx; 341 kcf_provider_desc_t *pd; 342 int error; 343 kcf_req_params_t params; 344 345 if ((ctx == NULL) || 346 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 347 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 348 return (CRYPTO_INVALID_CONTEXT); 349 } 350 351 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 352 353 /* The fast path for SW providers. */ 354 if (CHECK_FASTPATH(cr, pd)) { 355 error = KCF_PROV_DIGEST_UPDATE(pd, ctx, data, NULL); 356 KCF_PROV_INCRSTATS(pd, error); 357 } else { 358 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 359 ctx->cc_session, NULL, NULL, data, NULL); 360 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 361 } 362 363 return (error); 364 } 365 366 /* 367 * crypto_digest_final() 368 * 369 * Arguments: 370 * context: A crypto_context_t initialized by digest_init(). 371 * digest: The storage for the digest. 372 * cr: crypto_call_req_t calling conditions and call back info. 373 * 374 * Description: 375 * Asynchronously submits a request for, or synchronously performs the 376 * final part of a message digest operation. 377 * 378 * Context: 379 * Process or interrupt, according to the semantics dictated by the 'cr'. 380 * 381 * Returns: 382 * See comment in the beginning of the file. 383 */ 384 int 385 crypto_digest_final(crypto_context_t context, crypto_data_t *digest, 386 crypto_call_req_t *cr) 387 { 388 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 389 kcf_context_t *kcf_ctx; 390 kcf_provider_desc_t *pd; 391 int error; 392 kcf_req_params_t params; 393 394 if ((ctx == NULL) || 395 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 396 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 397 return (CRYPTO_INVALID_CONTEXT); 398 } 399 400 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 401 402 /* The fast path for SW providers. */ 403 if (CHECK_FASTPATH(cr, pd)) { 404 error = KCF_PROV_DIGEST_FINAL(pd, ctx, digest, NULL); 405 KCF_PROV_INCRSTATS(pd, error); 406 } else { 407 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_FINAL, 408 ctx->cc_session, NULL, NULL, NULL, digest); 409 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 410 } 411 412 /* Release the hold done in kcf_new_ctx() during init step. */ 413 KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 414 return (error); 415 } 416 417 /* 418 * Performs a digest update on the specified key. Note that there is 419 * no k-API crypto_digest_key() equivalent of this function. 420 */ 421 int 422 crypto_digest_key_prov(crypto_context_t context, crypto_key_t *key, 423 crypto_call_req_t *cr) 424 { 425 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 426 kcf_context_t *kcf_ctx; 427 kcf_provider_desc_t *pd; 428 int error; 429 kcf_req_params_t params; 430 431 if ((ctx == NULL) || 432 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 433 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 434 return (CRYPTO_INVALID_CONTEXT); 435 } 436 437 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 438 439 /* The fast path for SW providers. */ 440 if (CHECK_FASTPATH(cr, pd)) { 441 error = KCF_PROV_DIGEST_KEY(pd, ctx, key, NULL); 442 KCF_PROV_INCRSTATS(pd, error); 443 } else { 444 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_DIGEST_KEY, 445 ctx->cc_session, NULL, key, NULL, NULL); 446 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 447 } 448 449 return (error); 450 } 451 452 /* 453 * See comments for crypto_digest_update() and crypto_digest_final(). 454 */ 455 int 456 crypto_digest_single(crypto_context_t context, crypto_data_t *data, 457 crypto_data_t *digest, crypto_call_req_t *cr) 458 { 459 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 460 kcf_context_t *kcf_ctx; 461 kcf_provider_desc_t *pd; 462 int error; 463 kcf_req_params_t params; 464 465 if ((ctx == NULL) || 466 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 467 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 468 return (CRYPTO_INVALID_CONTEXT); 469 } 470 471 472 /* The fast path for SW providers. */ 473 if (CHECK_FASTPATH(cr, pd)) { 474 error = KCF_PROV_DIGEST(pd, ctx, data, digest, NULL); 475 KCF_PROV_INCRSTATS(pd, error); 476 } else { 477 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 478 NULL, NULL, data, digest); 479 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 480 } 481 482 /* Release the hold done in kcf_new_ctx() during init step. */ 483 KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 484 return (error); 485 } 486