Print this page
first pass


 184         return (mod_info(&modlinkage, modinfop));
 185 }
 186 
 187 
 188 /*
 189  * KCF software provider control entry points.
 190  */
 191 /* ARGSUSED */
 192 static void
 193 rc4_provider_status(crypto_provider_handle_t provider, uint_t *status)
 194 {
 195         *status = CRYPTO_PROVIDER_READY;
 196 }
 197 
 198 /* ARGSUSED */
 199 static int
 200 rc4_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 201     crypto_key_t *key, crypto_spi_ctx_template_t template,
 202     crypto_req_handle_t req)
 203 {
 204 
 205 /* EXPORT DELETE START */
 206 
 207         ARCFour_key *keystream;
 208 
 209         if ((mechanism)->cm_type != RC4_MECH_INFO_TYPE)
 210                 return (CRYPTO_MECHANISM_INVALID);
 211 
 212         if (key->ck_format != CRYPTO_KEY_RAW)
 213                 return (CRYPTO_KEY_TYPE_INCONSISTENT);
 214 
 215         if (key->ck_length < ARCFOUR_MIN_KEY_BITS ||
 216             key->ck_length > ARCFOUR_MAX_KEY_BITS) {
 217                 return (CRYPTO_KEY_SIZE_RANGE);
 218         }
 219 
 220         /*
 221          * Allocate an RC4 key stream.
 222          */
 223         if ((keystream = kmem_alloc(sizeof (ARCFour_key),
 224             crypto_kmflag(req))) == NULL)
 225                 return (CRYPTO_HOST_MEMORY);
 226 
 227         arcfour_key_init(keystream, key->ck_data,
 228             CRYPTO_BITS2BYTES(key->ck_length));
 229 
 230         ctx->cc_provider_private = keystream;
 231 
 232 /* EXPORT DELETE END */
 233 
 234         return (CRYPTO_SUCCESS);
 235 }
 236 
 237 static int
 238 rc4_crypt(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
 239     crypto_req_handle_t req)
 240 {
 241         int ret;
 242 
 243         ret = rc4_crypt_update(ctx, input, output, req);
 244 
 245         if (ret != CRYPTO_BUFFER_TOO_SMALL)
 246                 (void) rc4_free_context(ctx);
 247 
 248         return (ret);
 249 }
 250 
 251 /* ARGSUSED */
 252 static int
 253 rc4_crypt_update(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
 254     crypto_req_handle_t req)
 255 {
 256         int ret = CRYPTO_SUCCESS;
 257 
 258 /* EXPORT DELETE START */
 259 
 260         ARCFour_key *key;
 261         off_t saveoffset;
 262 
 263         ASSERT(ctx->cc_provider_private != NULL);
 264 
 265         if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && ctx->cc_opstate != NULL)
 266                 key = ctx->cc_opstate;
 267         else
 268                 key = ctx->cc_provider_private;
 269 
 270         /* Simple case: in-line encipherment */
 271 
 272         if (output == NULL) {
 273                 switch (input->cd_format) {
 274                 case CRYPTO_DATA_RAW: {
 275                         char *start, *end;
 276                         start = input->cd_raw.iov_base + input->cd_offset;
 277 
 278                         end =  input->cd_raw.iov_base + input->cd_raw.iov_len;
 279 


 467                             output, cur_len);
 468                         if (ret != CRYPTO_SUCCESS)
 469                                 return (ret);
 470 
 471                         length -= cur_len;
 472                         vec_idx++;
 473                         offset = 0;
 474                         output->cd_offset += cur_len;
 475                 }
 476 
 477                 if (vec_idx == uiop->uio_iovcnt && length > 0) {
 478 
 479                         return (CRYPTO_DATA_LEN_RANGE);
 480                 }
 481         }
 482         }
 483 
 484         output->cd_offset = saveoffset;
 485         output->cd_length = input->cd_length;
 486 
 487 /* EXPORT DELETE END */
 488 
 489         return (ret);
 490 }
 491 
 492 /* ARGSUSED */
 493 static int rc4_crypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
 494     crypto_req_handle_t req)
 495 {
 496         /* No final part for streams ciphers. Just free the context */
 497         if (data != NULL)
 498                 data->cd_length = 0;
 499 
 500         return (rc4_free_context(ctx));
 501 }
 502 
 503 /* ARGSUSED */
 504 static int
 505 rc4_crypt_atomic(crypto_provider_handle_t handle, crypto_session_id_t session,
 506     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *input,
 507     crypto_data_t *output, crypto_spi_ctx_template_t template,
 508     crypto_req_handle_t req)


 510         crypto_ctx_t ctx;
 511         int ret;
 512 
 513         bzero(&ctx, sizeof (crypto_ctx_t));
 514         ret = rc4_common_init(&ctx, mechanism, key, template, req);
 515 
 516         if (ret != CRYPTO_SUCCESS)
 517                 return (ret);
 518 
 519         ret = rc4_crypt_update(&ctx, input, output, req);
 520 
 521         (void) rc4_free_context(&ctx);
 522 
 523         return (ret);
 524 }
 525 
 526 /* ARGSUSED */
 527 static int
 528 rc4_free_context(crypto_ctx_t *ctx)
 529 {
 530 
 531 /* EXPORT DELETE START */
 532 
 533         ARCFour_key *keystream = ctx->cc_provider_private;
 534 
 535         if (keystream != NULL) {
 536                 bzero(keystream, sizeof (ARCFour_key));
 537                 kmem_free(keystream, sizeof (ARCFour_key));
 538                 ctx->cc_provider_private = NULL;
 539         }
 540 
 541 /* EXPORT DELETE END */
 542 
 543         return (CRYPTO_SUCCESS);
 544 }
 545 
 546 /* Encrypts a contiguous input 'in' into the 'out' crypto_data_t */
 547 
 548 static int
 549 crypto_arcfour_crypt(ARCFour_key *key, uchar_t *in, crypto_data_t *out,
 550     int length)
 551 {
 552         switch (out->cd_format) {
 553                 case CRYPTO_DATA_RAW: {
 554                         uchar_t *start, *end;
 555                         start = (uchar_t *)(out->cd_raw.iov_base +
 556                             out->cd_offset);
 557 
 558                         end = (uchar_t *)(out->cd_raw.iov_base +
 559                             out->cd_raw.iov_len);
 560 
 561                         if (start + out->cd_length > end)
 562                                 return (CRYPTO_DATA_LEN_RANGE);




 184         return (mod_info(&modlinkage, modinfop));
 185 }
 186 
 187 
 188 /*
 189  * KCF software provider control entry points.
 190  */
 191 /* ARGSUSED */
 192 static void
 193 rc4_provider_status(crypto_provider_handle_t provider, uint_t *status)
 194 {
 195         *status = CRYPTO_PROVIDER_READY;
 196 }
 197 
 198 /* ARGSUSED */
 199 static int
 200 rc4_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 201     crypto_key_t *key, crypto_spi_ctx_template_t template,
 202     crypto_req_handle_t req)
 203 {



 204         ARCFour_key *keystream;
 205 
 206         if ((mechanism)->cm_type != RC4_MECH_INFO_TYPE)
 207                 return (CRYPTO_MECHANISM_INVALID);
 208 
 209         if (key->ck_format != CRYPTO_KEY_RAW)
 210                 return (CRYPTO_KEY_TYPE_INCONSISTENT);
 211 
 212         if (key->ck_length < ARCFOUR_MIN_KEY_BITS ||
 213             key->ck_length > ARCFOUR_MAX_KEY_BITS) {
 214                 return (CRYPTO_KEY_SIZE_RANGE);
 215         }
 216 
 217         /*
 218          * Allocate an RC4 key stream.
 219          */
 220         if ((keystream = kmem_alloc(sizeof (ARCFour_key),
 221             crypto_kmflag(req))) == NULL)
 222                 return (CRYPTO_HOST_MEMORY);
 223 
 224         arcfour_key_init(keystream, key->ck_data,
 225             CRYPTO_BITS2BYTES(key->ck_length));
 226 
 227         ctx->cc_provider_private = keystream;
 228 


 229         return (CRYPTO_SUCCESS);
 230 }
 231 
 232 static int
 233 rc4_crypt(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
 234     crypto_req_handle_t req)
 235 {
 236         int ret;
 237 
 238         ret = rc4_crypt_update(ctx, input, output, req);
 239 
 240         if (ret != CRYPTO_BUFFER_TOO_SMALL)
 241                 (void) rc4_free_context(ctx);
 242 
 243         return (ret);
 244 }
 245 
 246 /* ARGSUSED */
 247 static int
 248 rc4_crypt_update(crypto_ctx_t *ctx, crypto_data_t *input, crypto_data_t *output,
 249     crypto_req_handle_t req)
 250 {
 251         int ret = CRYPTO_SUCCESS;
 252 


 253         ARCFour_key *key;
 254         off_t saveoffset;
 255 
 256         ASSERT(ctx->cc_provider_private != NULL);
 257 
 258         if ((ctx->cc_flags & CRYPTO_USE_OPSTATE) && ctx->cc_opstate != NULL)
 259                 key = ctx->cc_opstate;
 260         else
 261                 key = ctx->cc_provider_private;
 262 
 263         /* Simple case: in-line encipherment */
 264 
 265         if (output == NULL) {
 266                 switch (input->cd_format) {
 267                 case CRYPTO_DATA_RAW: {
 268                         char *start, *end;
 269                         start = input->cd_raw.iov_base + input->cd_offset;
 270 
 271                         end =  input->cd_raw.iov_base + input->cd_raw.iov_len;
 272 


 460                             output, cur_len);
 461                         if (ret != CRYPTO_SUCCESS)
 462                                 return (ret);
 463 
 464                         length -= cur_len;
 465                         vec_idx++;
 466                         offset = 0;
 467                         output->cd_offset += cur_len;
 468                 }
 469 
 470                 if (vec_idx == uiop->uio_iovcnt && length > 0) {
 471 
 472                         return (CRYPTO_DATA_LEN_RANGE);
 473                 }
 474         }
 475         }
 476 
 477         output->cd_offset = saveoffset;
 478         output->cd_length = input->cd_length;
 479 


 480         return (ret);
 481 }
 482 
 483 /* ARGSUSED */
 484 static int rc4_crypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
 485     crypto_req_handle_t req)
 486 {
 487         /* No final part for streams ciphers. Just free the context */
 488         if (data != NULL)
 489                 data->cd_length = 0;
 490 
 491         return (rc4_free_context(ctx));
 492 }
 493 
 494 /* ARGSUSED */
 495 static int
 496 rc4_crypt_atomic(crypto_provider_handle_t handle, crypto_session_id_t session,
 497     crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_data_t *input,
 498     crypto_data_t *output, crypto_spi_ctx_template_t template,
 499     crypto_req_handle_t req)


 501         crypto_ctx_t ctx;
 502         int ret;
 503 
 504         bzero(&ctx, sizeof (crypto_ctx_t));
 505         ret = rc4_common_init(&ctx, mechanism, key, template, req);
 506 
 507         if (ret != CRYPTO_SUCCESS)
 508                 return (ret);
 509 
 510         ret = rc4_crypt_update(&ctx, input, output, req);
 511 
 512         (void) rc4_free_context(&ctx);
 513 
 514         return (ret);
 515 }
 516 
 517 /* ARGSUSED */
 518 static int
 519 rc4_free_context(crypto_ctx_t *ctx)
 520 {



 521         ARCFour_key *keystream = ctx->cc_provider_private;
 522 
 523         if (keystream != NULL) {
 524                 bzero(keystream, sizeof (ARCFour_key));
 525                 kmem_free(keystream, sizeof (ARCFour_key));
 526                 ctx->cc_provider_private = NULL;
 527         }
 528 


 529         return (CRYPTO_SUCCESS);
 530 }
 531 
 532 /* Encrypts a contiguous input 'in' into the 'out' crypto_data_t */
 533 
 534 static int
 535 crypto_arcfour_crypt(ARCFour_key *key, uchar_t *in, crypto_data_t *out,
 536     int length)
 537 {
 538         switch (out->cd_format) {
 539                 case CRYPTO_DATA_RAW: {
 540                         uchar_t *start, *end;
 541                         start = (uchar_t *)(out->cd_raw.iov_base +
 542                             out->cd_offset);
 543 
 544                         end = (uchar_t *)(out->cd_raw.iov_base +
 545                             out->cd_raw.iov_len);
 546 
 547                         if (start + out->cd_length > end)
 548                                 return (CRYPTO_DATA_LEN_RANGE);