Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/crypto/io/dca_3des.c
+++ new/usr/src/uts/common/crypto/io/dca_3des.c
1 1
2 2 /*
3 3 * CDDL HEADER START
4 4 *
5 5 * The contents of this file are subject to the terms of the
6 6 * Common Development and Distribution License (the "License").
7 7 * You may not use this file except in compliance with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22
23 23 /*
24 - * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 + * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 */
27 27
28 -#pragma ident "%Z%%M% %I% %E% SMI"
29 -
30 28 /*
31 29 * Deimos - cryptographic acceleration based upon Broadcom 582x.
32 30 */
33 31
34 32 #include <sys/types.h>
35 33 #include <sys/ddi.h>
36 34 #include <sys/sunddi.h>
37 35 #include <sys/kmem.h>
38 36 #include <sys/note.h>
39 37 #include <sys/crypto/common.h>
40 38 #include <sys/crypto/spi.h>
41 39 #include <sys/crypto/dca.h>
42 40
41 +#if defined(__i386) || defined(__amd64)
42 +#include <sys/byteorder.h>
43 +#define UNALIGNED_POINTERS_PERMITTED
44 +#endif
45 +
43 46 /*
44 47 * 3DES implementation.
45 48 */
46 49
47 50 static int dca_3desstart(dca_t *, uint32_t, dca_request_t *);
48 51 static void dca_3desdone(dca_request_t *, int);
49 52
50 53
51 54 int
52 55 dca_3des(crypto_ctx_t *ctx, crypto_data_t *in,
53 56 crypto_data_t *out, crypto_req_handle_t req, int flags)
54 57 {
55 58 int len;
56 59 int rv;
57 60 dca_request_t *reqp = ctx->cc_provider_private;
58 61 dca_request_t *des_ctx = ctx->cc_provider_private;
59 62 dca_t *dca = ctx->cc_provider;
60 63 crypto_data_t *nin = &reqp->dr_ctx.in_dup;
61 64
62 65 len = dca_length(in);
63 66 if (len % DESBLOCK) {
64 67 DBG(dca, DWARN, "input not an integral number of DES blocks");
65 68 (void) dca_free_context(ctx);
66 69 if (flags & DR_DECRYPT) {
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
67 70 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
68 71 } else {
69 72 return (CRYPTO_DATA_LEN_RANGE);
70 73 }
71 74 }
72 75
73 76 /*
74 77 * If cd_miscdata non-null then this contains the IV.
75 78 */
76 79 if (in->cd_miscdata != NULL) {
80 +#ifdef UNALIGNED_POINTERS_PERMITTED
81 + uint32_t *p = (uint32_t *)in->cd_miscdata;
82 + des_ctx->dr_ctx.iv[0] = htonl(p[0]);
83 + des_ctx->dr_ctx.iv[1] = htonl(p[1]);
84 +#else
77 85 uchar_t *p = (uchar_t *)in->cd_miscdata;
78 86 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
79 87 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
88 +#endif /* UNALIGNED_POINTERS_PERMITTED */
80 89 }
81 90
82 91 if (len > dca_length(out)) {
83 92 DBG(dca, DWARN, "inadequate output space (need %d, got %d)",
84 93 len, dca_length(out));
85 94 out->cd_length = len;
86 95 /* Do not free the context since the app will call again */
87 96 return (CRYPTO_BUFFER_TOO_SMALL);
88 97 }
89 98
90 99 if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
91 100 (void) dca_free_context(ctx);
92 101 return (rv);
93 102 }
94 103
95 104 /* special handling for null-sized input buffers */
96 105 if (len == 0) {
97 106 out->cd_length = 0;
98 107 (void) dca_free_context(ctx);
99 108 return (CRYPTO_SUCCESS);
100 109 }
101 110
102 111 /*
103 112 * Make a local copy of the input crypto_data_t structure. This
104 113 * allows it to be manipulated locally and for dealing with in-place
105 114 * data (ie in == out). Note that "nin" has been pre-allocated,
106 115 * and only fields are copied, not actual data.
107 116 */
108 117 if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
109 118 (void) dca_free_context(ctx);
110 119 return (rv);
111 120 }
112 121
113 122 /* Set output to zero ready to take the processed data */
114 123 out->cd_length = 0;
115 124
116 125 reqp->dr_kcf_req = req;
117 126 reqp->dr_in = nin;
118 127 reqp->dr_out = out;
119 128 reqp->dr_job_stat = DS_3DESJOBS;
120 129 reqp->dr_byte_stat = DS_3DESBYTES;
121 130
122 131 rv = dca_3desstart(dca, flags, reqp);
123 132
124 133 /* Context will be freed in the kCF callback function otherwise */
125 134 if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
126 135 (void) dca_free_context(ctx);
127 136 }
128 137 return (rv);
129 138 }
130 139
131 140
132 141 void
133 142 dca_3desctxfree(void *arg)
134 143 {
135 144 crypto_ctx_t *ctx = (crypto_ctx_t *)arg;
136 145 dca_request_t *des_ctx = ctx->cc_provider_private;
137 146
138 147 if (des_ctx == NULL)
139 148 return;
140 149
141 150 des_ctx->dr_ctx.atomic = 0;
142 151 des_ctx->dr_ctx.ctx_cm_type = 0;
143 152 ctx->cc_provider_private = NULL;
144 153
145 154 if (des_ctx->destroy)
146 155 dca_destroyreq(des_ctx);
147 156 else
148 157 /* Return it to the pool */
149 158 dca_freereq(des_ctx);
150 159 }
151 160
152 161 int
153 162 dca_3desupdate(crypto_ctx_t *ctx, crypto_data_t *in,
154 163 crypto_data_t *out, crypto_req_handle_t req, int flags)
155 164 {
156 165 int len;
157 166 int rawlen;
158 167 int rv;
159 168 dca_request_t *reqp = ctx->cc_provider_private;
160 169 dca_request_t *des_ctx = ctx->cc_provider_private;
↓ open down ↓ |
71 lines elided |
↑ open up ↑ |
161 170 dca_t *dca = ctx->cc_provider;
162 171 crypto_data_t *nin = &reqp->dr_ctx.in_dup;
163 172
164 173 rawlen = dca_length(in) + des_ctx->dr_ctx.residlen;
165 174
166 175 len = ROUNDDOWN(rawlen, DESBLOCK);
167 176 /*
168 177 * If cd_miscdata non-null then this contains the IV.
169 178 */
170 179 if (in->cd_miscdata != NULL) {
180 +#ifdef UNALIGNED_POINTERS_PERMITTED
181 + uint32_t *p = (uint32_t *)in->cd_miscdata;
182 + des_ctx->dr_ctx.iv[0] = htonl(p[0]);
183 + des_ctx->dr_ctx.iv[1] = htonl(p[1]);
184 +#else
171 185 uchar_t *p = (uchar_t *)in->cd_miscdata;
172 186 des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
173 187 des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
188 +#endif /* UNALIGNED_POINTERS_PERMITTED */
174 189 }
175 190
176 191 if (len > dca_length(out)) {
177 192 DBG(dca, DWARN, "not enough output space (need %d, got %d)",
178 193 len, dca_length(out));
179 194 out->cd_length = len;
180 195 /* Do not free the context since the app will call again */
181 196 return (CRYPTO_BUFFER_TOO_SMALL);
182 197 }
183 198
184 199 if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
185 200 (void) dca_free_context(ctx);
186 201 return (rv);
187 202 }
188 203
189 204 reqp->dr_kcf_req = req;
190 205
191 206 /*
192 207 * From here on out, we are committed.
193 208 */
194 209
195 210 if (len == 0) {
196 211 /*
197 212 * No blocks being encrypted, so we just accumulate the
198 213 * input for the next pass and return.
199 214 */
200 215 if ((rv = dca_getbufbytes(in, 0,
201 216 (rawlen % DESBLOCK) - des_ctx->dr_ctx.residlen,
202 217 des_ctx->dr_ctx.resid + des_ctx->dr_ctx.residlen)) !=
203 218 CRYPTO_SUCCESS) {
204 219 DBG(dca, DWARN,
205 220 "dca_3desupdate: dca_getbufbytes() failed for residual only pass");
206 221 dca_freereq(reqp);
207 222 return (rv);
208 223 }
209 224 des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
210 225
211 226 out->cd_length = 0;
212 227 /*
213 228 * Do not free the context here since it will be done
214 229 * in the final function
215 230 */
216 231 return (CRYPTO_SUCCESS);
217 232 }
218 233
219 234 /*
220 235 * Set up rbuf for previous residual data.
221 236 */
222 237 if (des_ctx->dr_ctx.residlen) {
223 238 bcopy(des_ctx->dr_ctx.resid, des_ctx->dr_ctx.activeresid,
224 239 des_ctx->dr_ctx.residlen);
225 240 des_ctx->dr_ctx.activeresidlen = des_ctx->dr_ctx.residlen;
226 241 }
227 242
228 243 /*
229 244 * Locate and save residual data for next encrypt_update.
230 245 */
231 246 if ((rv = dca_getbufbytes(in, len - des_ctx->dr_ctx.residlen,
232 247 rawlen % DESBLOCK, des_ctx->dr_ctx.resid)) != CRYPTO_SUCCESS) {
233 248 DBG(dca, DWARN, "dca_3desupdate: dca_getbufbytes() failed");
234 249 (void) dca_free_context(ctx);
235 250 return (rv);
236 251 }
237 252
238 253 /* Calculate new residual length. */
239 254 des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
240 255
241 256 /*
242 257 * Make a local copy of the input crypto_data_t structure. This
243 258 * allows it to be manipulated locally and for dealing with in-place
244 259 * data (ie in == out).
245 260 */
246 261 if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
247 262 (void) dca_free_context(ctx);
248 263 return (rv);
249 264 }
250 265
251 266 /* Set output to zero ready to take the processed data */
252 267 out->cd_length = 0;
253 268
254 269 reqp->dr_in = nin;
255 270 reqp->dr_out = out;
256 271 reqp->dr_job_stat = DS_3DESJOBS;
257 272 reqp->dr_byte_stat = DS_3DESBYTES;
258 273
259 274 rv = dca_3desstart(dca, flags, reqp);
260 275
261 276 /*
262 277 * As this is multi-part the context is cleared on success
263 278 * (CRYPTO_QUEUED) in dca_3desfinal().
264 279 */
265 280
266 281 if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
267 282 (void) dca_free_context(ctx);
268 283 }
269 284 return (rv);
270 285 }
271 286
272 287 int
273 288 dca_3desfinal(crypto_ctx_t *ctx, crypto_data_t *out, int mode)
274 289 {
275 290 dca_request_t *des_ctx = ctx->cc_provider_private;
276 291 dca_t *dca = ctx->cc_provider;
277 292 int rv = CRYPTO_SUCCESS;
278 293
279 294 ASSERT(ctx->cc_provider_private != NULL);
280 295 /*
281 296 * There must be no unprocessed ciphertext/plaintext.
282 297 * This happens if the length of the last data is
283 298 * not a multiple of the DES block length.
284 299 */
285 300 if (des_ctx->dr_ctx.residlen != 0) {
286 301 DBG(dca, DWARN, "dca_3desfinal: invalid nonzero residual");
287 302 if (mode & DR_DECRYPT) {
288 303 rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
289 304 } else {
290 305 rv = CRYPTO_DATA_LEN_RANGE;
291 306 }
292 307 }
293 308 (void) dca_free_context(ctx);
294 309 out->cd_length = 0;
295 310 return (rv);
296 311 }
297 312
298 313 int
299 314 dca_3desatomic(crypto_provider_handle_t provider,
300 315 crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
301 316 crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
302 317 int kmflag, crypto_req_handle_t req, int mode)
303 318 {
304 319 crypto_ctx_t ctx; /* on the stack */
305 320 int rv;
306 321
307 322 ctx.cc_provider = provider;
308 323 ctx.cc_session = session_id;
309 324
310 325 /*
311 326 * Input must be a multiple of the block size. This test only
312 327 * works for non-padded mechanisms when the blocksize is 2^N.
313 328 */
314 329 if ((dca_length(input) & (DESBLOCK - 1)) != 0) {
315 330 DBG(NULL, DWARN, "dca_3desatomic: input not multiple of BS");
316 331 if (mode & DR_DECRYPT) {
317 332 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
318 333 } else {
319 334 return (CRYPTO_DATA_LEN_RANGE);
320 335 }
321 336 }
322 337
323 338 rv = dca_3desctxinit(&ctx, mechanism, key, kmflag, mode);
324 339 if (rv != CRYPTO_SUCCESS) {
325 340 DBG(NULL, DWARN, "dca_3desatomic: dca_3desctxinit() failed");
326 341 return (rv);
327 342 }
328 343
329 344 /*
330 345 * Set the atomic flag so that the hardware callback function
331 346 * will free the context.
332 347 */
333 348 ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
334 349
335 350 /* check for inplace ops */
336 351 if (input == output) {
337 352 ((dca_request_t *)ctx.cc_provider_private)->dr_flags
338 353 |= DR_INPLACE;
339 354 }
340 355
341 356 rv = dca_3des(&ctx, input, output, req, mode);
342 357 if ((rv != CRYPTO_QUEUED) && (rv != CRYPTO_SUCCESS)) {
343 358 DBG(NULL, DWARN, "dca_3desatomic: dca_3des() failed");
344 359 output->cd_length = 0;
345 360 }
346 361
347 362 /*
348 363 * The features of dca_3desfinal() are implemented within
349 364 * dca_3desdone() due to the asynchronous nature of dca_3des().
350 365 */
351 366
352 367 /*
353 368 * The context will be freed in the hardware callback function if it
354 369 * is queued
355 370 */
356 371 if (rv != CRYPTO_QUEUED)
357 372 dca_3desctxfree(&ctx);
358 373
359 374 return (rv);
360 375 }
361 376
362 377 int
363 378 dca_3desstart(dca_t *dca, uint32_t flags, dca_request_t *reqp)
364 379 {
365 380 size_t len;
366 381 crypto_data_t *in = reqp->dr_in;
367 382 int rv;
368 383 dca_request_t *ctx = reqp;
369 384 uint32_t iv[2];
370 385
371 386 /*
372 387 * Preconditions:
373 388 * 1) in and out point to the "right" buffers.
374 389 * 2) in->b_bcount - in->b_resid == initial offset
375 390 * 3) likewise for out
376 391 * 4) there is enough space in the output
377 392 * 5) we perform a block for block encrypt
378 393 */
379 394 len = ctx->dr_ctx.activeresidlen + dca_length(in);
380 395 len = ROUNDDOWN(min(len, MAXPACKET), DESBLOCK);
381 396 reqp->dr_pkt_length = (uint16_t)len;
382 397
383 398 /* collect IVs for this pass */
384 399 iv[0] = ctx->dr_ctx.iv[0];
↓ open down ↓ |
201 lines elided |
↑ open up ↑ |
385 400 iv[1] = ctx->dr_ctx.iv[1];
386 401
387 402 /*
388 403 * And also, for decrypt, collect the IV for the next pass. For
389 404 * decrypt, the IV must be collected BEFORE decryption, or else
390 405 * we will lose it. (For encrypt, we grab the IV AFTER encryption,
391 406 * in dca_3desdone.
392 407 */
393 408 if (flags & DR_DECRYPT) {
394 409 uchar_t ivstore[DESBLOCK];
410 +#ifdef UNALIGNED_POINTERS_PERMITTED
411 + uint32_t *ivp = (uint32_t *)ivstore;
412 +#else
395 413 uchar_t *ivp = ivstore;
414 +#endif /* UNALIGNED_POINTERS_PERMITTED */
396 415
397 416 /* get last 8 bytes of ciphertext for IV of next op */
398 417 /*
399 418 * If we're processing only a DESBLOCKS worth of data
400 419 * and there is active residual present then it will be
401 420 * needed for the IV also.
402 421 */
403 422 if ((len == DESBLOCK) && ctx->dr_ctx.activeresidlen) {
404 423 /* Bring the active residual into play */
405 424 bcopy(ctx->dr_ctx.activeresid, ivstore,
406 425 ctx->dr_ctx.activeresidlen);
407 426 rv = dca_getbufbytes(in, 0,
408 427 DESBLOCK - ctx->dr_ctx.activeresidlen,
409 428 ivstore + ctx->dr_ctx.activeresidlen);
410 429 } else {
411 430 rv = dca_getbufbytes(in,
412 431 len - DESBLOCK - ctx->dr_ctx.activeresidlen,
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
413 432 DESBLOCK, ivstore);
414 433 }
415 434
416 435 if (rv != CRYPTO_SUCCESS) {
417 436 DBG(dca, DWARN,
418 437 "dca_3desstart: dca_getbufbytes() failed");
419 438 return (rv);
420 439 }
421 440
422 441 /* store as a pair of native 32-bit values */
442 +#ifdef UNALIGNED_POINTERS_PERMITTED
443 + ctx->dr_ctx.iv[0] = htonl(ivp[0]);
444 + ctx->dr_ctx.iv[1] = htonl(ivp[1]);
445 +#else
423 446 ctx->dr_ctx.iv[0] =
424 447 ivp[0]<<24 | ivp[1]<<16 | ivp[2]<<8 | ivp[3];
425 448 ctx->dr_ctx.iv[1] =
426 449 ivp[4]<<24 | ivp[5]<<16 | ivp[6]<<8 | ivp[7];
450 +#endif /* UNALIGNED_POINTERS_PERMITTED */
427 451 }
428 452
429 453 /* For now we force a pullup. Add direct DMA later. */
430 454 reqp->dr_flags &= ~(DR_SCATTER | DR_GATHER);
431 455 if ((len < dca_mindma) || (ctx->dr_ctx.activeresidlen > 0) ||
432 456 dca_sgcheck(dca, reqp->dr_in, DCA_SG_CONTIG) ||
433 457 dca_sgcheck(dca, reqp->dr_out, DCA_SG_WALIGN)) {
434 458 reqp->dr_flags |= DR_SCATTER | DR_GATHER;
435 459 }
436 460
437 461 /* Try to do direct DMA. */
438 462 if (!(reqp->dr_flags & (DR_SCATTER | DR_GATHER))) {
439 463 if (dca_bindchains(reqp, len, len) == DDI_SUCCESS) {
440 464 reqp->dr_in->cd_offset += len;
441 465 reqp->dr_in->cd_length -= len;
442 466 } else {
443 467 DBG(dca, DWARN,
444 468 "dca_3desstart: dca_bindchains() failed");
445 469 return (CRYPTO_DEVICE_ERROR);
446 470 }
447 471 }
448 472
449 473 /* gather the data into the device */
450 474 if (reqp->dr_flags & DR_GATHER) {
451 475 rv = dca_resid_gather(in, (char *)ctx->dr_ctx.activeresid,
452 476 &ctx->dr_ctx.activeresidlen, reqp->dr_ibuf_kaddr, len);
453 477 if (rv != CRYPTO_SUCCESS) {
454 478 DBG(dca, DWARN,
455 479 "dca_3desstart: dca_resid_gather() failed");
456 480 return (rv);
457 481 }
458 482 /*
459 483 * Setup for scattering the result back out
460 484 * The output buffer is a multi-entry chain for x86 and
461 485 * a single entry chain for Sparc.
462 486 * Use the actual length if the first entry is sufficient.
463 487 */
464 488 (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, len,
465 489 DDI_DMA_SYNC_FORDEV);
466 490 if (dca_check_dma_handle(dca, reqp->dr_ibuf_dmah,
467 491 DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
468 492 reqp->destroy = TRUE;
469 493 return (CRYPTO_DEVICE_ERROR);
470 494 }
471 495
472 496 reqp->dr_in_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
473 497 reqp->dr_in_next = reqp->dr_ibuf_head.dc_next_paddr;
474 498 if (len > reqp->dr_ibuf_head.dc_buffer_length)
475 499 reqp->dr_in_len = reqp->dr_ibuf_head.dc_buffer_length;
476 500 else
477 501 reqp->dr_in_len = len;
478 502 }
479 503 /*
480 504 * Setup for scattering the result back out
481 505 * The output buffer is a multi-entry chain for x86 and
482 506 * a single entry chain for Sparc.
483 507 * Use the actual length if the first entry is sufficient.
484 508 */
485 509 if (reqp->dr_flags & DR_SCATTER) {
486 510 reqp->dr_out_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
487 511 reqp->dr_out_next = reqp->dr_obuf_head.dc_next_paddr;
488 512 if (len > reqp->dr_obuf_head.dc_buffer_length)
489 513 reqp->dr_out_len = reqp->dr_obuf_head.dc_buffer_length;
490 514 else
491 515 reqp->dr_out_len = len;
492 516 }
493 517
494 518 reqp->dr_flags |= flags;
495 519 reqp->dr_callback = dca_3desdone;
496 520
497 521 /* write out the context structure */
498 522 PUTCTX32(reqp, CTX_3DESIVHI, iv[0]);
499 523 PUTCTX32(reqp, CTX_3DESIVLO, iv[1]);
500 524
501 525 /* schedule the work by doing a submit */
502 526 return (dca_start(dca, reqp, MCR1, 1));
503 527 }
504 528
505 529 void
506 530 dca_3desdone(dca_request_t *reqp, int errno)
507 531 {
508 532 crypto_data_t *out = reqp->dr_out;
509 533 dca_request_t *ctx = reqp;
510 534 ASSERT(ctx != NULL);
511 535
512 536 if (errno == CRYPTO_SUCCESS) {
513 537 size_t off;
514 538 /*
515 539 * Save the offset: this has to be done *before* dca_scatter
516 540 * modifies the buffer. We take the initial offset into the
517 541 * first buf, and add that to the total packet size to find
518 542 * the end of the packet.
519 543 */
520 544 off = dca_length(out) + reqp->dr_pkt_length - DESBLOCK;
521 545
522 546 if (reqp->dr_flags & DR_SCATTER) {
523 547 (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0,
524 548 reqp->dr_out_len, DDI_DMA_SYNC_FORKERNEL);
525 549 if (dca_check_dma_handle(reqp->dr_dca,
526 550 reqp->dr_obuf_dmah, DCA_FM_ECLASS_NONE) !=
527 551 DDI_SUCCESS) {
528 552 reqp->destroy = TRUE;
529 553 errno = CRYPTO_DEVICE_ERROR;
530 554 goto errout;
531 555 }
532 556
533 557 errno = dca_scatter(reqp->dr_obuf_kaddr,
534 558 reqp->dr_out, reqp->dr_out_len, 0);
535 559 if (errno != CRYPTO_SUCCESS) {
536 560 DBG(NULL, DWARN,
537 561 "dca_3desdone: dca_scatter() failed");
538 562 goto errout;
539 563 }
540 564
541 565 } else {
542 566 /* we've processed some more data */
↓ open down ↓ |
106 lines elided |
↑ open up ↑ |
543 567 out->cd_length += reqp->dr_pkt_length;
544 568 }
545 569
546 570
547 571 /*
548 572 * For encryption only, we have to grab the IV for the
549 573 * next pass AFTER encryption.
550 574 */
551 575 if (reqp->dr_flags & DR_ENCRYPT) {
552 576 uchar_t ivstore[DESBLOCK];
577 +#ifdef UNALIGNED_POINTERS_PERMITTED
578 + uint32_t *iv = (uint32_t *)ivstore;
579 +#else
553 580 uchar_t *iv = ivstore;
581 +#endif /* UNALIGNED_POINTERS_PERMITTED */
554 582
555 583 /* get last 8 bytes for IV of next op */
556 - errno = dca_getbufbytes(out, off, DESBLOCK, iv);
584 + errno = dca_getbufbytes(out, off, DESBLOCK,
585 + (uchar_t *)iv);
557 586 if (errno != CRYPTO_SUCCESS) {
558 587 DBG(NULL, DWARN,
559 588 "dca_3desdone: dca_getbufbytes() failed");
560 589 goto errout;
561 590 }
591 +
562 592 /* store as a pair of native 32-bit values */
593 +#ifdef UNALIGNED_POINTERS_PERMITTED
594 + ctx->dr_ctx.iv[0] = htonl(iv[0]);
595 + ctx->dr_ctx.iv[1] = htonl(iv[1]);
596 +#else
563 597 ctx->dr_ctx.iv[0] =
564 598 iv[0]<<24 | iv[1]<<16 | iv[2]<<8 | iv[3];
565 599 ctx->dr_ctx.iv[1] =
566 600 iv[4]<<24 | iv[5]<<16 | iv[6]<<8 | iv[7];
601 +#endif /* UNALIGNED_POINTERS_PERMITTED */
567 602 }
568 603
569 604 /*
570 605 * If there is more to do, then reschedule another
571 606 * pass.
572 607 */
573 608 if (dca_length(reqp->dr_in) >= 8) {
574 609 errno = dca_3desstart(reqp->dr_dca, reqp->dr_flags,
575 610 reqp);
576 611 if (errno == CRYPTO_QUEUED) {
577 612 return;
578 613 }
579 614 }
580 615 }
581 616
582 617 errout:
583 618
584 619 /*
585 620 * If this is an atomic operation perform the final function
586 621 * tasks (equivalent to to dca_3desfinal()).
587 622 */
588 623 if (reqp->dr_ctx.atomic) {
589 624 if ((errno == CRYPTO_SUCCESS) && (ctx->dr_ctx.residlen != 0)) {
590 625 DBG(NULL, DWARN,
591 626 "dca_3desdone: invalid nonzero residual");
592 627 if (reqp->dr_flags & DR_DECRYPT) {
593 628 errno = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
594 629 } else {
595 630 errno = CRYPTO_DATA_LEN_RANGE;
596 631 }
597 632 }
598 633 }
599 634
600 635 ASSERT(reqp->dr_kcf_req != NULL);
601 636 /* notify framework that request is completed */
602 637 crypto_op_notification(reqp->dr_kcf_req, errno);
603 638 DBG(NULL, DINTR,
604 639 "dca_3desdone: returning %d to the kef via crypto_op_notification",
605 640 errno);
606 641
607 642 /* This has to be done after notifing the framework */
608 643 if (reqp->dr_ctx.atomic) {
609 644 reqp->dr_context = NULL;
610 645 reqp->dr_ctx.atomic = 0;
611 646 reqp->dr_ctx.ctx_cm_type = 0;
612 647 if (reqp->destroy)
613 648 dca_destroyreq(reqp);
614 649 else
615 650 dca_freereq(reqp);
↓ open down ↓ |
39 lines elided |
↑ open up ↑ |
616 651 }
617 652 }
618 653
619 654 /* ARGSUSED */
620 655 int
621 656 dca_3desctxinit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
622 657 crypto_key_t *key, int kmflag, int flags)
623 658 {
624 659 dca_request_t *des_ctx;
625 660 dca_t *dca = ctx->cc_provider;
661 +#ifdef UNALIGNED_POINTERS_PERMITTED
662 + uint32_t *param;
663 + uint32_t *value32;
664 +#else
626 665 uchar_t *param;
666 +#endif /* UNALIGNED_POINTERS_PERMITTED */
627 667 uchar_t *value;
628 668 size_t paramsz;
629 669 unsigned len;
630 670 int i, j;
631 671
632 672 paramsz = mechanism->cm_param_len;
673 +#ifdef UNALIGNED_POINTERS_PERMITTED
674 + param = (uint32_t *)mechanism->cm_param;
675 +#else
633 676 param = (uchar_t *)mechanism->cm_param;
677 +#endif /* UNALIGNED_POINTERS_PERMITTED */
678 +
634 679 if ((paramsz != 0) && (paramsz != DES_IV_LEN)) {
635 680 DBG(NULL, DWARN,
636 681 "dca_3desctxinit: parameter(IV) length not %d (%d)",
637 682 DES_IV_LEN, paramsz);
638 683 return (CRYPTO_MECHANISM_PARAM_INVALID);
639 684 }
640 685
641 686 if ((des_ctx = dca_getreq(dca, MCR1, 1)) == NULL) {
642 687 dca_error(dca, "unable to allocate request for 3DES");
643 688 return (CRYPTO_HOST_MEMORY);
644 689 }
645 690 /*
646 691 * Identify and store the IV as a pair of native 32-bit words.
647 692 *
648 693 * If cm_param == NULL then the IV comes from the cd_miscdata field
649 694 * in the crypto_data structure.
650 695 */
651 696 if (param != NULL) {
652 697 ASSERT(paramsz == DES_IV_LEN);
698 +#ifdef UNALIGNED_POINTERS_PERMITTED
699 + des_ctx->dr_ctx.iv[0] = htonl(param[0]);
700 + des_ctx->dr_ctx.iv[1] = htonl(param[1]);
701 +#else
653 702 des_ctx->dr_ctx.iv[0] = param[0]<<24 | param[1]<<16 |
654 703 param[2]<<8 | param[3];
655 704 des_ctx->dr_ctx.iv[1] = param[4]<<24 | param[5]<<16 |
656 705 param[6]<<8 | param[7];
706 +#endif /* UNALIGNED_POINTERS_PERMITTED */
657 707 }
658 708 des_ctx->dr_ctx.residlen = 0;
659 709 des_ctx->dr_ctx.activeresidlen = 0;
660 710 des_ctx->dr_ctx.ctx_cm_type = mechanism->cm_type;
661 711 ctx->cc_provider_private = des_ctx;
662 712
663 713 if (key->ck_format != CRYPTO_KEY_RAW) {
664 714 DBG(NULL, DWARN,
665 715 "dca_3desctxinit: only raw crypto key type support with DES/3DES");
666 716 dca_3desctxfree(ctx);
667 717 return (CRYPTO_KEY_TYPE_INCONSISTENT);
668 718 }
669 719
670 720 len = key->ck_length;
671 721 value = (uchar_t *)key->ck_data;
672 722
673 723 if (flags & DR_TRIPLE) {
674 724 /* 3DES */
675 725 switch (len) {
676 726 case 192:
677 727 for (i = 0; i < 6; i++) {
678 728 des_ctx->dr_ctx.key[i] = 0;
679 729 for (j = 0; j < 4; j++) {
680 730 des_ctx->dr_ctx.key[i] <<= 8;
681 731 des_ctx->dr_ctx.key[i] |= *value;
682 732 value++;
683 733 }
684 734 }
685 735 break;
686 736
687 737 case 128:
688 738 for (i = 0; i < 4; i++) {
689 739 des_ctx->dr_ctx.key[i] = 0;
690 740 for (j = 0; j < 4; j++) {
691 741 des_ctx->dr_ctx.key[i] <<= 8;
692 742 des_ctx->dr_ctx.key[i] |= *value;
693 743 value++;
694 744 }
695 745 }
696 746 des_ctx->dr_ctx.key[4] = des_ctx->dr_ctx.key[0];
697 747 des_ctx->dr_ctx.key[5] = des_ctx->dr_ctx.key[1];
698 748 break;
699 749
700 750 default:
701 751 DBG(NULL, DWARN, "Incorrect 3DES keysize (%d)", len);
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
702 752 dca_3desctxfree(ctx);
703 753 return (CRYPTO_KEY_SIZE_RANGE);
704 754 }
705 755 } else {
706 756 /* single DES */
707 757 if (len != 64) {
708 758 DBG(NULL, DWARN, "Incorrect DES keysize (%d)", len);
709 759 dca_3desctxfree(ctx);
710 760 return (CRYPTO_KEY_SIZE_RANGE);
711 761 }
762 +
763 +#ifdef UNALIGNED_POINTERS_PERMITTED
764 + value32 = (uint32_t *)value;
765 + des_ctx->dr_ctx.key[0] = htonl(value32[0]);
766 + des_ctx->dr_ctx.key[1] = htonl(value32[1]);
767 +#else
712 768 des_ctx->dr_ctx.key[0] =
713 769 value[0]<<24 | value[1]<<16 | value[2]<<8 | value[3];
714 770 des_ctx->dr_ctx.key[1] =
715 771 value[4]<<24 | value[5]<<16 | value[6]<<8 | value[7];
772 +#endif /* UNALIGNED_POINTERS_PERMITTED */
773 +
716 774 /* for single des just repeat des key */
717 775 des_ctx->dr_ctx.key[4] =
718 776 des_ctx->dr_ctx.key[2] = des_ctx->dr_ctx.key[0];
719 777 des_ctx->dr_ctx.key[5] =
720 778 des_ctx->dr_ctx.key[3] = des_ctx->dr_ctx.key[1];
721 779 }
722 780
723 781 /*
724 782 * Setup the context here so that we do not need to setup it up
725 783 * for every update
726 784 */
727 785 PUTCTX16(des_ctx, CTX_LENGTH, CTX_3DES_LENGTH);
728 786 PUTCTX16(des_ctx, CTX_CMD, CMD_3DES);
729 787 PUTCTX32(des_ctx, CTX_3DESDIRECTION,
730 788 flags & DR_ENCRYPT ? CTX_3DES_ENCRYPT : CTX_3DES_DECRYPT);
731 789 PUTCTX32(des_ctx, CTX_3DESKEY1HI, des_ctx->dr_ctx.key[0]);
732 790 PUTCTX32(des_ctx, CTX_3DESKEY1LO, des_ctx->dr_ctx.key[1]);
733 791 PUTCTX32(des_ctx, CTX_3DESKEY2HI, des_ctx->dr_ctx.key[2]);
734 792 PUTCTX32(des_ctx, CTX_3DESKEY2LO, des_ctx->dr_ctx.key[3]);
735 793 PUTCTX32(des_ctx, CTX_3DESKEY3HI, des_ctx->dr_ctx.key[4]);
736 794 PUTCTX32(des_ctx, CTX_3DESKEY3LO, des_ctx->dr_ctx.key[5]);
737 795
738 796 return (CRYPTO_SUCCESS);
739 797 }
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX