Print this page
4896 Performance improvements for KCF AES modes
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/crypto/io/blowfish.c
+++ new/usr/src/uts/common/crypto/io/blowfish.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 +/*
26 + * Copyright 2015 by Saso Kiselkov. All rights reserved.
27 + */
25 28
26 29 /*
27 30 * Blowfish provider for the Kernel Cryptographic Framework (KCF)
28 31 */
29 32
30 33 #include <sys/types.h>
31 34 #include <sys/systm.h>
32 35 #include <sys/modctl.h>
33 36 #include <sys/cmn_err.h>
34 37 #include <sys/ddi.h>
35 38 #include <sys/crypto/common.h>
36 39 #include <sys/crypto/spi.h>
37 40 #include <sys/sysmacros.h>
38 41 #include <sys/strsun.h>
39 42 #include <sys/note.h>
40 43 #include <modes/modes.h>
41 44 #include <blowfish/blowfish_impl.h>
42 45
43 46 extern struct mod_ops mod_cryptoops;
44 47
45 48 /*
46 49 * Module linkage information for the kernel.
47 50 */
48 51 static struct modlcrypto modlcrypto = {
49 52 &mod_cryptoops,
50 53 "Blowfish Kernel SW Provider"
51 54 };
52 55
53 56 static struct modlinkage modlinkage = {
54 57 MODREV_1,
55 58 (void *)&modlcrypto,
56 59 NULL
57 60 };
58 61
59 62 /*
60 63 * CSPI information (entry points, provider info, etc.)
61 64 */
62 65 typedef enum blowfish_mech_type {
63 66 BLOWFISH_ECB_MECH_INFO_TYPE, /* SUN_CKM_BLOWFISH_ECB */
64 67 BLOWFISH_CBC_MECH_INFO_TYPE /* SUN_CKM_BLOWFISH_CBC */
65 68 } blowfish_mech_type_t;
66 69
67 70
68 71 #define BLOWFISH_COPY_BLOCK(src, dst) \
69 72 (dst)[0] = (src)[0]; \
70 73 (dst)[1] = (src)[1]; \
71 74 (dst)[2] = (src)[2]; \
72 75 (dst)[3] = (src)[3]; \
73 76 (dst)[4] = (src)[4]; \
74 77 (dst)[5] = (src)[5]; \
75 78 (dst)[6] = (src)[6]; \
76 79 (dst)[7] = (src)[7]
77 80
78 81 #define BLOWFISH_XOR_BLOCK(src, dst) \
79 82 (dst)[0] ^= (src)[0]; \
80 83 (dst)[1] ^= (src)[1]; \
81 84 (dst)[2] ^= (src)[2]; \
82 85 (dst)[3] ^= (src)[3]; \
83 86 (dst)[4] ^= (src)[4]; \
84 87 (dst)[5] ^= (src)[5]; \
85 88 (dst)[6] ^= (src)[6]; \
86 89 (dst)[7] ^= (src)[7]
87 90
88 91 /*
89 92 * Mechanism info structure passed to KCF during registration.
90 93 */
91 94
92 95 static crypto_mech_info_t blowfish_mech_info_tab[] = {
93 96 /* BLOWFISH_ECB */
94 97 {SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE,
95 98 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
96 99 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
97 100 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS},
98 101 /* BLOWFISH_CBC */
99 102 {SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE,
100 103 CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
101 104 CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
102 105 BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}
103 106 };
104 107
105 108 #define BLOWFISH_VALID_MECH(mech) \
106 109 (((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE || \
107 110 (mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0)
108 111
109 112 /* operations are in-place if the output buffer is NULL */
110 113 #define BLOWFISH_ARG_INPLACE(input, output) \
111 114 if ((output) == NULL) \
112 115 (output) = (input);
113 116
114 117 static void blowfish_provider_status(crypto_provider_handle_t, uint_t *);
115 118
116 119 static crypto_control_ops_t blowfish_control_ops = {
117 120 blowfish_provider_status
118 121 };
119 122
120 123 static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *,
121 124 crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
122 125 static int blowfish_common_init_ctx(blowfish_ctx_t *,
123 126 crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int);
124 127 static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *,
125 128 crypto_req_handle_t);
126 129 static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *,
127 130 crypto_req_handle_t);
128 131
129 132 static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
130 133 crypto_req_handle_t);
131 134 static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *,
132 135 crypto_data_t *, crypto_req_handle_t);
133 136 static int blowfish_encrypt_atomic(crypto_provider_handle_t,
134 137 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
135 138 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
136 139
137 140 static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
138 141 crypto_req_handle_t);
139 142 static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *,
140 143 crypto_data_t *, crypto_req_handle_t);
141 144 static int blowfish_decrypt_atomic(crypto_provider_handle_t,
142 145 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
143 146 crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
144 147
145 148 static crypto_cipher_ops_t blowfish_cipher_ops = {
146 149 blowfish_common_init,
147 150 blowfish_encrypt,
148 151 blowfish_encrypt_update,
149 152 blowfish_encrypt_final,
150 153 blowfish_encrypt_atomic,
151 154 blowfish_common_init,
152 155 blowfish_decrypt,
153 156 blowfish_decrypt_update,
154 157 blowfish_decrypt_final,
155 158 blowfish_decrypt_atomic
156 159 };
157 160
158 161 static int blowfish_create_ctx_template(crypto_provider_handle_t,
159 162 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
160 163 size_t *, crypto_req_handle_t);
161 164 static int blowfish_free_context(crypto_ctx_t *);
162 165
163 166 static crypto_ctx_ops_t blowfish_ctx_ops = {
164 167 blowfish_create_ctx_template,
165 168 blowfish_free_context
166 169 };
167 170
168 171 static crypto_ops_t blowfish_crypto_ops = {
169 172 &blowfish_control_ops,
170 173 NULL,
171 174 &blowfish_cipher_ops,
172 175 NULL,
173 176 NULL,
174 177 NULL,
175 178 NULL,
176 179 NULL,
177 180 NULL,
178 181 NULL,
179 182 NULL,
180 183 NULL,
181 184 NULL,
182 185 &blowfish_ctx_ops
183 186 };
184 187
185 188 static crypto_provider_info_t blowfish_prov_info = {
186 189 CRYPTO_SPI_VERSION_1,
187 190 "Blowfish Software Provider",
188 191 CRYPTO_SW_PROVIDER,
189 192 {&modlinkage},
190 193 NULL,
191 194 &blowfish_crypto_ops,
192 195 sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t),
193 196 blowfish_mech_info_tab
194 197 };
195 198
196 199
197 200 static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL;
198 201
199 202 int
200 203 _init(void)
201 204 {
202 205 int ret;
203 206
204 207 if ((ret = mod_install(&modlinkage)) != 0)
205 208 return (ret);
206 209
207 210 /* Register with KCF. If the registration fails, remove the module. */
208 211 if (crypto_register_provider(&blowfish_prov_info,
209 212 &blowfish_prov_handle)) {
210 213 (void) mod_remove(&modlinkage);
211 214 return (EACCES);
212 215 }
213 216
214 217 return (0);
215 218 }
216 219
217 220 int
218 221 _fini(void)
219 222 {
220 223 /* Unregister from KCF if module is registered */
221 224 if (blowfish_prov_handle != NULL) {
222 225 if (crypto_unregister_provider(blowfish_prov_handle))
223 226 return (EBUSY);
224 227
225 228 blowfish_prov_handle = NULL;
226 229 }
227 230
228 231 return (mod_remove(&modlinkage));
229 232 }
230 233
231 234 int
232 235 _info(struct modinfo *modinfop)
233 236 {
234 237 return (mod_info(&modlinkage, modinfop));
235 238 }
236 239
237 240 /*
238 241 * Initialize key schedules for blowfish
239 242 */
240 243 static int
241 244 init_keysched(crypto_key_t *key, void *keysched)
242 245 {
243 246 /*
244 247 * Only keys by value are supported by this module.
245 248 */
246 249 switch (key->ck_format) {
247 250 case CRYPTO_KEY_RAW:
248 251 if (key->ck_length < BLOWFISH_MINBITS ||
249 252 key->ck_length > BLOWFISH_MAXBITS) {
250 253 return (CRYPTO_KEY_SIZE_RANGE);
251 254 }
252 255 break;
253 256 default:
254 257 return (CRYPTO_KEY_TYPE_INCONSISTENT);
255 258 }
256 259
257 260 blowfish_init_keysched(key->ck_data, key->ck_length, keysched);
258 261 return (CRYPTO_SUCCESS);
259 262 }
260 263
261 264 /*
262 265 * KCF software provider control entry points.
263 266 */
264 267 /* ARGSUSED */
265 268 static void
266 269 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status)
267 270 {
268 271 *status = CRYPTO_PROVIDER_READY;
269 272 }
270 273
271 274 /*
272 275 * KCF software provider encrypt entry points.
273 276 */
274 277 static int
275 278 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
276 279 crypto_key_t *key, crypto_spi_ctx_template_t template,
277 280 crypto_req_handle_t req)
278 281 {
279 282 blowfish_ctx_t *blowfish_ctx;
280 283 int rv;
281 284 int kmflag;
282 285
283 286 /*
284 287 * Only keys by value are supported by this module.
285 288 */
286 289 if (key->ck_format != CRYPTO_KEY_RAW) {
287 290 return (CRYPTO_KEY_TYPE_INCONSISTENT);
288 291 }
289 292
290 293 if (!BLOWFISH_VALID_MECH(mechanism))
291 294 return (CRYPTO_MECHANISM_INVALID);
292 295
293 296 if (mechanism->cm_param != NULL &&
294 297 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
295 298 return (CRYPTO_MECHANISM_PARAM_INVALID);
296 299
297 300 kmflag = crypto_kmflag(req);
298 301 switch (mechanism->cm_type) {
299 302 case BLOWFISH_ECB_MECH_INFO_TYPE:
300 303 blowfish_ctx = ecb_alloc_ctx(kmflag);
301 304 break;
302 305 case BLOWFISH_CBC_MECH_INFO_TYPE:
303 306 blowfish_ctx = cbc_alloc_ctx(kmflag);
304 307 break;
305 308 }
306 309 if (blowfish_ctx == NULL)
307 310 return (CRYPTO_HOST_MEMORY);
308 311
309 312 rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
310 313 key, kmflag);
311 314 if (rv != CRYPTO_SUCCESS) {
↓ open down ↓ |
277 lines elided |
↑ open up ↑ |
312 315 crypto_free_mode_ctx(blowfish_ctx);
313 316 return (rv);
314 317 }
315 318
316 319 ctx->cc_provider_private = blowfish_ctx;
317 320
318 321 return (CRYPTO_SUCCESS);
319 322 }
320 323
321 324 static void
322 -blowfish_copy_block64(uint8_t *in, uint64_t *out)
325 +blowfish_copy_block64(const uint8_t *in, uint64_t *out)
323 326 {
324 327 if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
325 328 /* LINTED: pointer alignment */
326 329 out[0] = *(uint64_t *)&in[0];
327 330 } else {
328 331 uint8_t *iv8 = (uint8_t *)&out[0];
329 332
330 333 BLOWFISH_COPY_BLOCK(in, iv8);
331 334 }
332 335 }
333 336
334 337 /* ARGSUSED */
335 338 static int
336 339 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
337 340 crypto_data_t *ciphertext, crypto_req_handle_t req)
338 341 {
339 342 int ret;
340 343
341 344 blowfish_ctx_t *blowfish_ctx;
342 345
343 346 /*
344 347 * Plaintext must be a multiple of blowfish block size.
345 348 * This test only works for non-padded mechanisms
346 349 * when blocksize is 2^N.
347 350 */
348 351 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
349 352 return (CRYPTO_DATA_LEN_RANGE);
350 353
351 354 ASSERT(ctx->cc_provider_private != NULL);
352 355 blowfish_ctx = ctx->cc_provider_private;
353 356
354 357 BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
355 358
356 359 /*
357 360 * We need to just return the length needed to store the output.
358 361 * We should not destroy the context for the following case.
359 362 */
360 363 if (ciphertext->cd_length < plaintext->cd_length) {
361 364 ciphertext->cd_length = plaintext->cd_length;
362 365 return (CRYPTO_BUFFER_TOO_SMALL);
363 366 }
364 367
365 368 /*
366 369 * Do an update on the specified input data.
367 370 */
368 371 ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
369 372 ASSERT(blowfish_ctx->bc_remainder_len == 0);
370 373 (void) blowfish_free_context(ctx);
371 374
372 375 /* LINTED */
373 376 return (ret);
374 377 }
375 378
376 379 /* ARGSUSED */
377 380 static int
378 381 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
379 382 crypto_data_t *plaintext, crypto_req_handle_t req)
380 383 {
381 384 int ret;
382 385
383 386 blowfish_ctx_t *blowfish_ctx;
384 387
385 388 /*
386 389 * Ciphertext must be a multiple of blowfish block size.
387 390 * This test only works for non-padded mechanisms
388 391 * when blocksize is 2^N.
389 392 */
390 393 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
391 394 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
392 395
393 396 ASSERT(ctx->cc_provider_private != NULL);
394 397 blowfish_ctx = ctx->cc_provider_private;
395 398
396 399 BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
397 400
398 401 /*
399 402 * We need to just return the length needed to store the output.
400 403 * We should not destroy the context for the following case.
401 404 */
402 405 if (plaintext->cd_length < ciphertext->cd_length) {
403 406 plaintext->cd_length = ciphertext->cd_length;
404 407 return (CRYPTO_BUFFER_TOO_SMALL);
405 408 }
406 409
407 410 /*
408 411 * Do an update on the specified input data.
409 412 */
410 413 ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req);
411 414 ASSERT(blowfish_ctx->bc_remainder_len == 0);
412 415 (void) blowfish_free_context(ctx);
413 416
414 417 /* LINTED */
415 418 return (ret);
416 419 }
417 420
418 421 /* ARGSUSED */
419 422 static int
420 423 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
421 424 crypto_data_t *ciphertext, crypto_req_handle_t req)
422 425 {
423 426 off_t saved_offset;
424 427 size_t saved_length, out_len;
425 428 int ret = CRYPTO_SUCCESS;
426 429
427 430 ASSERT(ctx->cc_provider_private != NULL);
428 431
429 432 BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
430 433
431 434 /* compute number of bytes that will hold the ciphertext */
432 435 out_len =
433 436 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
434 437 out_len += plaintext->cd_length;
435 438 out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
436 439
437 440 /* return length needed to store the output */
438 441 if (ciphertext->cd_length < out_len) {
439 442 ciphertext->cd_length = out_len;
440 443 return (CRYPTO_BUFFER_TOO_SMALL);
441 444 }
442 445
443 446 saved_offset = ciphertext->cd_offset;
444 447 saved_length = ciphertext->cd_length;
445 448
446 449 /*
447 450 * Do the blowfish update on the specified input data.
448 451 */
449 452 switch (plaintext->cd_format) {
450 453 case CRYPTO_DATA_RAW:
451 454 ret = crypto_update_iov(ctx->cc_provider_private,
452 455 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
453 456 blowfish_copy_block64);
454 457 break;
455 458 case CRYPTO_DATA_UIO:
456 459 ret = crypto_update_uio(ctx->cc_provider_private,
457 460 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
458 461 blowfish_copy_block64);
459 462 break;
460 463 case CRYPTO_DATA_MBLK:
461 464 ret = crypto_update_mp(ctx->cc_provider_private,
462 465 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
463 466 blowfish_copy_block64);
464 467 break;
465 468 default:
466 469 ret = CRYPTO_ARGUMENTS_BAD;
467 470 }
468 471
469 472 if (ret == CRYPTO_SUCCESS) {
470 473 if (plaintext != ciphertext)
471 474 ciphertext->cd_length =
472 475 ciphertext->cd_offset - saved_offset;
473 476 } else {
474 477 ciphertext->cd_length = saved_length;
475 478 }
476 479 ciphertext->cd_offset = saved_offset;
477 480
478 481 return (ret);
479 482 }
480 483
481 484 /* ARGSUSED */
482 485 static int
483 486 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
484 487 crypto_data_t *plaintext, crypto_req_handle_t req)
485 488 {
486 489 off_t saved_offset;
487 490 size_t saved_length, out_len;
488 491 int ret = CRYPTO_SUCCESS;
489 492
490 493 ASSERT(ctx->cc_provider_private != NULL);
491 494
492 495 BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
493 496
494 497 /* compute number of bytes that will hold the plaintext */
495 498 out_len =
496 499 ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
497 500 out_len += ciphertext->cd_length;
498 501 out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
499 502
500 503 /* return length needed to store the output */
501 504 if (plaintext->cd_length < out_len) {
502 505 plaintext->cd_length = out_len;
503 506 return (CRYPTO_BUFFER_TOO_SMALL);
504 507 }
505 508
506 509 saved_offset = plaintext->cd_offset;
507 510 saved_length = plaintext->cd_length;
508 511
509 512 /*
510 513 * Do the blowfish update on the specified input data.
511 514 */
512 515 switch (ciphertext->cd_format) {
513 516 case CRYPTO_DATA_RAW:
514 517 ret = crypto_update_iov(ctx->cc_provider_private,
515 518 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
516 519 blowfish_copy_block64);
517 520 break;
518 521 case CRYPTO_DATA_UIO:
519 522 ret = crypto_update_uio(ctx->cc_provider_private,
520 523 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
521 524 blowfish_copy_block64);
522 525 break;
523 526 case CRYPTO_DATA_MBLK:
524 527 ret = crypto_update_mp(ctx->cc_provider_private,
525 528 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
526 529 blowfish_copy_block64);
527 530 break;
528 531 default:
529 532 ret = CRYPTO_ARGUMENTS_BAD;
530 533 }
531 534
532 535 if (ret == CRYPTO_SUCCESS) {
533 536 if (ciphertext != plaintext)
534 537 plaintext->cd_length =
535 538 plaintext->cd_offset - saved_offset;
536 539 } else {
537 540 plaintext->cd_length = saved_length;
538 541 }
539 542 plaintext->cd_offset = saved_offset;
540 543
541 544 return (ret);
542 545 }
543 546
544 547 /* ARGSUSED */
545 548 static int
546 549 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
547 550 crypto_req_handle_t req)
548 551 {
549 552 blowfish_ctx_t *blowfish_ctx;
550 553
551 554 ASSERT(ctx->cc_provider_private != NULL);
552 555 blowfish_ctx = ctx->cc_provider_private;
553 556
554 557 /*
555 558 * There must be no unprocessed data.
556 559 * This happens if the length of the last data is
557 560 * not a multiple of the BLOWFISH block length.
558 561 */
559 562 if (blowfish_ctx->bc_remainder_len > 0)
560 563 return (CRYPTO_DATA_LEN_RANGE);
561 564
562 565 (void) blowfish_free_context(ctx);
563 566 data->cd_length = 0;
564 567
565 568 return (CRYPTO_SUCCESS);
566 569 }
567 570
568 571 /* ARGSUSED */
569 572 static int
570 573 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
571 574 crypto_req_handle_t req)
572 575 {
573 576 blowfish_ctx_t *blowfish_ctx;
574 577
575 578 ASSERT(ctx->cc_provider_private != NULL);
576 579 blowfish_ctx = ctx->cc_provider_private;
577 580
578 581 /*
579 582 * There must be no unprocessed ciphertext.
580 583 * This happens if the length of the last ciphertext is
581 584 * not a multiple of the BLOWFISH block length.
582 585 */
583 586 if (blowfish_ctx->bc_remainder_len > 0)
584 587 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
585 588
586 589 (void) blowfish_free_context(ctx);
587 590 data->cd_length = 0;
588 591
589 592 return (CRYPTO_SUCCESS);
590 593 }
591 594
592 595 /* ARGSUSED */
593 596 static int
594 597 blowfish_encrypt_atomic(crypto_provider_handle_t provider,
595 598 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
596 599 crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
597 600 crypto_spi_ctx_template_t template, crypto_req_handle_t req)
598 601 {
599 602 blowfish_ctx_t blowfish_ctx; /* on the stack */
600 603 off_t saved_offset;
601 604 size_t saved_length;
602 605 int ret;
603 606
604 607 BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
605 608
606 609 /*
607 610 * Plaintext must be a multiple of blowfish block size.
608 611 * This test only works for non-padded mechanisms
609 612 * when blocksize is 2^N.
610 613 */
611 614 if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
612 615 return (CRYPTO_DATA_LEN_RANGE);
613 616
614 617 /* return length needed to store the output */
615 618 if (ciphertext->cd_length < plaintext->cd_length) {
616 619 ciphertext->cd_length = plaintext->cd_length;
617 620 return (CRYPTO_BUFFER_TOO_SMALL);
618 621 }
619 622
620 623 if (!BLOWFISH_VALID_MECH(mechanism))
621 624 return (CRYPTO_MECHANISM_INVALID);
622 625
623 626 if (mechanism->cm_param_len != 0 &&
624 627 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
625 628 return (CRYPTO_MECHANISM_PARAM_INVALID);
626 629
627 630 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
628 631
629 632 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
630 633 key, crypto_kmflag(req));
631 634 if (ret != CRYPTO_SUCCESS)
632 635 return (ret);
633 636
634 637 saved_offset = ciphertext->cd_offset;
635 638 saved_length = ciphertext->cd_length;
636 639
637 640 /*
638 641 * Do an update on the specified input data.
639 642 */
640 643 switch (plaintext->cd_format) {
641 644 case CRYPTO_DATA_RAW:
642 645 ret = crypto_update_iov(&blowfish_ctx,
643 646 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
644 647 blowfish_copy_block64);
645 648 break;
646 649 case CRYPTO_DATA_UIO:
647 650 ret = crypto_update_uio(&blowfish_ctx,
648 651 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
649 652 blowfish_copy_block64);
650 653 break;
651 654 case CRYPTO_DATA_MBLK:
652 655 ret = crypto_update_mp((void *)&blowfish_ctx,
653 656 plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
654 657 blowfish_copy_block64);
655 658 break;
656 659 default:
657 660 ret = CRYPTO_ARGUMENTS_BAD;
658 661 }
659 662
660 663 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
661 664 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
662 665 kmem_free(blowfish_ctx.bc_keysched,
663 666 blowfish_ctx.bc_keysched_len);
664 667 }
665 668
666 669 if (ret == CRYPTO_SUCCESS) {
667 670 ASSERT(blowfish_ctx.bc_remainder_len == 0);
668 671 if (plaintext != ciphertext)
669 672 ciphertext->cd_length =
670 673 ciphertext->cd_offset - saved_offset;
671 674 } else {
672 675 ciphertext->cd_length = saved_length;
673 676 }
674 677 ciphertext->cd_offset = saved_offset;
675 678
676 679 return (ret);
677 680 }
678 681
679 682 /* ARGSUSED */
680 683 static int
681 684 blowfish_decrypt_atomic(crypto_provider_handle_t provider,
682 685 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
683 686 crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
684 687 crypto_spi_ctx_template_t template, crypto_req_handle_t req)
685 688 {
686 689 blowfish_ctx_t blowfish_ctx; /* on the stack */
687 690 off_t saved_offset;
688 691 size_t saved_length;
689 692 int ret;
690 693
691 694 BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
692 695
693 696 /*
694 697 * Ciphertext must be a multiple of blowfish block size.
695 698 * This test only works for non-padded mechanisms
696 699 * when blocksize is 2^N.
697 700 */
698 701 if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
699 702 return (CRYPTO_DATA_LEN_RANGE);
700 703
701 704 /* return length needed to store the output */
702 705 if (plaintext->cd_length < ciphertext->cd_length) {
703 706 plaintext->cd_length = ciphertext->cd_length;
704 707 return (CRYPTO_BUFFER_TOO_SMALL);
705 708 }
706 709
707 710 if (!BLOWFISH_VALID_MECH(mechanism))
708 711 return (CRYPTO_MECHANISM_INVALID);
709 712
710 713 if (mechanism->cm_param_len != 0 &&
711 714 mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
712 715 return (CRYPTO_MECHANISM_PARAM_INVALID);
713 716
714 717 bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
715 718
716 719 ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
717 720 key, crypto_kmflag(req));
718 721 if (ret != CRYPTO_SUCCESS)
719 722 return (ret);
720 723
721 724 saved_offset = plaintext->cd_offset;
722 725 saved_length = plaintext->cd_length;
723 726
724 727 /*
725 728 * Do an update on the specified input data.
726 729 */
727 730 switch (ciphertext->cd_format) {
728 731 case CRYPTO_DATA_RAW:
729 732 ret = crypto_update_iov(&blowfish_ctx,
730 733 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
731 734 blowfish_copy_block64);
732 735 break;
733 736 case CRYPTO_DATA_UIO:
734 737 ret = crypto_update_uio(&blowfish_ctx,
735 738 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
736 739 blowfish_copy_block64);
737 740 break;
738 741 case CRYPTO_DATA_MBLK:
739 742 ret = crypto_update_mp(&blowfish_ctx,
740 743 ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
741 744 blowfish_copy_block64);
742 745 break;
743 746 default:
744 747 ret = CRYPTO_ARGUMENTS_BAD;
745 748 }
746 749
747 750 if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
748 751 bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
749 752 kmem_free(blowfish_ctx.bc_keysched,
750 753 blowfish_ctx.bc_keysched_len);
751 754 }
752 755
753 756 if (ret == CRYPTO_SUCCESS) {
754 757 ASSERT(blowfish_ctx.bc_remainder_len == 0);
755 758 if (ciphertext != plaintext)
756 759 plaintext->cd_length =
757 760 plaintext->cd_offset - saved_offset;
758 761 } else {
759 762 plaintext->cd_length = saved_length;
760 763 }
761 764 plaintext->cd_offset = saved_offset;
762 765
763 766 return (ret);
764 767 }
765 768
766 769 /*
767 770 * KCF software provider context template entry points.
768 771 */
769 772 /* ARGSUSED */
770 773 static int
771 774 blowfish_create_ctx_template(crypto_provider_handle_t provider,
772 775 crypto_mechanism_t *mechanism, crypto_key_t *key,
773 776 crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
774 777 {
775 778 void *keysched;
776 779 size_t size;
777 780 int rv;
778 781
779 782 if (!BLOWFISH_VALID_MECH(mechanism))
780 783 return (CRYPTO_MECHANISM_INVALID);
781 784
782 785 if ((keysched = blowfish_alloc_keysched(&size,
783 786 crypto_kmflag(req))) == NULL) {
784 787 return (CRYPTO_HOST_MEMORY);
785 788 }
786 789
787 790 /*
788 791 * Initialize key schedule. Key length information is stored
789 792 * in the key.
790 793 */
791 794 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
792 795 bzero(keysched, size);
793 796 kmem_free(keysched, size);
794 797 return (rv);
795 798 }
796 799
797 800 *tmpl = keysched;
798 801 *tmpl_size = size;
799 802
800 803 return (CRYPTO_SUCCESS);
801 804 }
802 805
803 806 /* ARGSUSED */
804 807 static int
805 808 blowfish_free_context(crypto_ctx_t *ctx)
806 809 {
807 810 blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
808 811
809 812 if (blowfish_ctx != NULL) {
810 813 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
811 814 ASSERT(blowfish_ctx->bc_keysched_len != 0);
812 815 bzero(blowfish_ctx->bc_keysched,
813 816 blowfish_ctx->bc_keysched_len);
814 817 kmem_free(blowfish_ctx->bc_keysched,
815 818 blowfish_ctx->bc_keysched_len);
816 819 }
817 820 crypto_free_mode_ctx(blowfish_ctx);
818 821 ctx->cc_provider_private = NULL;
819 822 }
820 823
821 824 return (CRYPTO_SUCCESS);
822 825 }
823 826
824 827 /* ARGSUSED */
825 828 static int
826 829 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
827 830 crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
828 831 crypto_key_t *key, int kmflag)
829 832 {
830 833 int rv = CRYPTO_SUCCESS;
831 834
832 835 void *keysched;
833 836 size_t size;
834 837
835 838 if (template == NULL) {
836 839 if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
837 840 return (CRYPTO_HOST_MEMORY);
838 841 /*
839 842 * Initialize key schedule.
840 843 * Key length is stored in the key.
841 844 */
842 845 if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
843 846 kmem_free(keysched, size);
844 847
845 848 blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
846 849 blowfish_ctx->bc_keysched_len = size;
847 850 } else {
848 851 keysched = template;
849 852 }
850 853 blowfish_ctx->bc_keysched = keysched;
851 854
852 855 switch (mechanism->cm_type) {
853 856 case BLOWFISH_CBC_MECH_INFO_TYPE:
854 857 rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx,
855 858 mechanism->cm_param, mechanism->cm_param_len,
856 859 BLOWFISH_BLOCK_LEN, blowfish_copy_block64);
857 860 break;
858 861 case BLOWFISH_ECB_MECH_INFO_TYPE:
859 862 blowfish_ctx->bc_flags |= ECB_MODE;
860 863 }
861 864
862 865 if (rv != CRYPTO_SUCCESS) {
863 866 if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
864 867 bzero(keysched, size);
865 868 kmem_free(keysched, size);
866 869 }
867 870 }
868 871
869 872 return (rv);
870 873 }
↓ open down ↓ |
538 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX