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);
|