5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * Deimos - cryptographic acceleration based upon Broadcom 582x.
32 #include <sys/types.h>
34 #include <sys/sunddi.h>
37 #include <sys/crypto/common.h>
38 #include <sys/crypto/spi.h>
39 #include <sys/crypto/dca.h>
41 #if defined(__i386) || defined(__amd64)
42 #include <sys/byteorder.h>
43 #define UNALIGNED_POINTERS_PERMITTED
47 * 3DES implementation.
50 static int dca_3desstart(dca_t
*, uint32_t, dca_request_t
*);
51 static void dca_3desdone(dca_request_t
*, int);
55 dca_3des(crypto_ctx_t
*ctx
, crypto_data_t
*in
,
56 crypto_data_t
*out
, crypto_req_handle_t req
, int flags
)
60 dca_request_t
*reqp
= ctx
->cc_provider_private
;
61 dca_request_t
*des_ctx
= ctx
->cc_provider_private
;
62 dca_t
*dca
= ctx
->cc_provider
;
63 crypto_data_t
*nin
= &reqp
->dr_ctx
.in_dup
;
67 DBG(dca
, DWARN
, "input not an integral number of DES blocks");
68 (void) dca_free_context(ctx
);
69 if (flags
& DR_DECRYPT
) {
70 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
72 return (CRYPTO_DATA_LEN_RANGE
);
77 * If cd_miscdata non-null then this contains the IV.
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]);
85 uchar_t
*p
= (uchar_t
*)in
->cd_miscdata
;
86 des_ctx
->dr_ctx
.iv
[0] = p
[0]<<24 | p
[1]<<16 | p
[2]<<8 | p
[3];
87 des_ctx
->dr_ctx
.iv
[1] = p
[4]<<24 | p
[5]<<16 | p
[6]<<8 | p
[7];
88 #endif /* UNALIGNED_POINTERS_PERMITTED */
91 if (len
> dca_length(out
)) {
92 DBG(dca
, DWARN
, "inadequate output space (need %d, got %d)",
93 len
, dca_length(out
));
95 /* Do not free the context since the app will call again */
96 return (CRYPTO_BUFFER_TOO_SMALL
);
99 if ((rv
= dca_verifyio(in
, out
)) != CRYPTO_SUCCESS
) {
100 (void) dca_free_context(ctx
);
104 /* special handling for null-sized input buffers */
107 (void) dca_free_context(ctx
);
108 return (CRYPTO_SUCCESS
);
112 * Make a local copy of the input crypto_data_t structure. This
113 * allows it to be manipulated locally and for dealing with in-place
114 * data (ie in == out). Note that "nin" has been pre-allocated,
115 * and only fields are copied, not actual data.
117 if ((rv
= dca_dupcrypto(in
, nin
)) != CRYPTO_SUCCESS
) {
118 (void) dca_free_context(ctx
);
122 /* Set output to zero ready to take the processed data */
125 reqp
->dr_kcf_req
= req
;
128 reqp
->dr_job_stat
= DS_3DESJOBS
;
129 reqp
->dr_byte_stat
= DS_3DESBYTES
;
131 rv
= dca_3desstart(dca
, flags
, reqp
);
133 /* Context will be freed in the kCF callback function otherwise */
134 if (rv
!= CRYPTO_QUEUED
&& rv
!= CRYPTO_BUFFER_TOO_SMALL
) {
135 (void) dca_free_context(ctx
);
142 dca_3desctxfree(void *arg
)
144 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)arg
;
145 dca_request_t
*des_ctx
= ctx
->cc_provider_private
;
150 des_ctx
->dr_ctx
.atomic
= 0;
151 des_ctx
->dr_ctx
.ctx_cm_type
= 0;
152 ctx
->cc_provider_private
= NULL
;
154 if (des_ctx
->destroy
)
155 dca_destroyreq(des_ctx
);
157 /* Return it to the pool */
158 dca_freereq(des_ctx
);
162 dca_3desupdate(crypto_ctx_t
*ctx
, crypto_data_t
*in
,
163 crypto_data_t
*out
, crypto_req_handle_t req
, int flags
)
168 dca_request_t
*reqp
= ctx
->cc_provider_private
;
169 dca_request_t
*des_ctx
= ctx
->cc_provider_private
;
170 dca_t
*dca
= ctx
->cc_provider
;
171 crypto_data_t
*nin
= &reqp
->dr_ctx
.in_dup
;
173 rawlen
= dca_length(in
) + des_ctx
->dr_ctx
.residlen
;
175 len
= ROUNDDOWN(rawlen
, DESBLOCK
);
177 * If cd_miscdata non-null then this contains the IV.
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]);
185 uchar_t
*p
= (uchar_t
*)in
->cd_miscdata
;
186 des_ctx
->dr_ctx
.iv
[0] = p
[0]<<24 | p
[1]<<16 | p
[2]<<8 | p
[3];
187 des_ctx
->dr_ctx
.iv
[1] = p
[4]<<24 | p
[5]<<16 | p
[6]<<8 | p
[7];
188 #endif /* UNALIGNED_POINTERS_PERMITTED */
191 if (len
> dca_length(out
)) {
192 DBG(dca
, DWARN
, "not enough output space (need %d, got %d)",
193 len
, dca_length(out
));
194 out
->cd_length
= len
;
195 /* Do not free the context since the app will call again */
196 return (CRYPTO_BUFFER_TOO_SMALL
);
199 if ((rv
= dca_verifyio(in
, out
)) != CRYPTO_SUCCESS
) {
200 (void) dca_free_context(ctx
);
204 reqp
->dr_kcf_req
= req
;
207 * From here on out, we are committed.
212 * No blocks being encrypted, so we just accumulate the
213 * input for the next pass and return.
215 if ((rv
= dca_getbufbytes(in
, 0,
216 (rawlen
% DESBLOCK
) - des_ctx
->dr_ctx
.residlen
,
217 des_ctx
->dr_ctx
.resid
+ des_ctx
->dr_ctx
.residlen
)) !=
220 "dca_3desupdate: dca_getbufbytes() failed for residual only pass");
224 des_ctx
->dr_ctx
.residlen
= rawlen
% DESBLOCK
;
228 * Do not free the context here since it will be done
229 * in the final function
231 return (CRYPTO_SUCCESS
);
235 * Set up rbuf for previous residual data.
237 if (des_ctx
->dr_ctx
.residlen
) {
238 bcopy(des_ctx
->dr_ctx
.resid
, des_ctx
->dr_ctx
.activeresid
,
239 des_ctx
->dr_ctx
.residlen
);
240 des_ctx
->dr_ctx
.activeresidlen
= des_ctx
->dr_ctx
.residlen
;
244 * Locate and save residual data for next encrypt_update.
246 if ((rv
= dca_getbufbytes(in
, len
- des_ctx
->dr_ctx
.residlen
,
247 rawlen
% DESBLOCK
, des_ctx
->dr_ctx
.resid
)) != CRYPTO_SUCCESS
) {
248 DBG(dca
, DWARN
, "dca_3desupdate: dca_getbufbytes() failed");
249 (void) dca_free_context(ctx
);
253 /* Calculate new residual length. */
254 des_ctx
->dr_ctx
.residlen
= rawlen
% DESBLOCK
;
257 * Make a local copy of the input crypto_data_t structure. This
258 * allows it to be manipulated locally and for dealing with in-place
259 * data (ie in == out).
261 if ((rv
= dca_dupcrypto(in
, nin
)) != CRYPTO_SUCCESS
) {
262 (void) dca_free_context(ctx
);
266 /* Set output to zero ready to take the processed data */
271 reqp
->dr_job_stat
= DS_3DESJOBS
;
272 reqp
->dr_byte_stat
= DS_3DESBYTES
;
274 rv
= dca_3desstart(dca
, flags
, reqp
);
277 * As this is multi-part the context is cleared on success
278 * (CRYPTO_QUEUED) in dca_3desfinal().
281 if (rv
!= CRYPTO_QUEUED
&& rv
!= CRYPTO_BUFFER_TOO_SMALL
) {
282 (void) dca_free_context(ctx
);
288 dca_3desfinal(crypto_ctx_t
*ctx
, crypto_data_t
*out
, int mode
)
290 dca_request_t
*des_ctx
= ctx
->cc_provider_private
;
291 dca_t
*dca
= ctx
->cc_provider
;
292 int rv
= CRYPTO_SUCCESS
;
294 ASSERT(ctx
->cc_provider_private
!= NULL
);
296 * There must be no unprocessed ciphertext/plaintext.
297 * This happens if the length of the last data is
298 * not a multiple of the DES block length.
300 if (des_ctx
->dr_ctx
.residlen
!= 0) {
301 DBG(dca
, DWARN
, "dca_3desfinal: invalid nonzero residual");
302 if (mode
& DR_DECRYPT
) {
303 rv
= CRYPTO_ENCRYPTED_DATA_LEN_RANGE
;
305 rv
= CRYPTO_DATA_LEN_RANGE
;
308 (void) dca_free_context(ctx
);
314 dca_3desatomic(crypto_provider_handle_t provider
,
315 crypto_session_id_t session_id
, crypto_mechanism_t
*mechanism
,
316 crypto_key_t
*key
, crypto_data_t
*input
, crypto_data_t
*output
,
317 int kmflag
, crypto_req_handle_t req
, int mode
)
319 crypto_ctx_t ctx
; /* on the stack */
322 ctx
.cc_provider
= provider
;
323 ctx
.cc_session
= session_id
;
326 * Input must be a multiple of the block size. This test only
327 * works for non-padded mechanisms when the blocksize is 2^N.
329 if ((dca_length(input
) & (DESBLOCK
- 1)) != 0) {
330 DBG(NULL
, DWARN
, "dca_3desatomic: input not multiple of BS");
331 if (mode
& DR_DECRYPT
) {
332 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
334 return (CRYPTO_DATA_LEN_RANGE
);
338 rv
= dca_3desctxinit(&ctx
, mechanism
, key
, kmflag
, mode
);
339 if (rv
!= CRYPTO_SUCCESS
) {
340 DBG(NULL
, DWARN
, "dca_3desatomic: dca_3desctxinit() failed");
345 * Set the atomic flag so that the hardware callback function
346 * will free the context.
348 ((dca_request_t
*)ctx
.cc_provider_private
)->dr_ctx
.atomic
= 1;
350 /* check for inplace ops */
351 if (input
== output
) {
352 ((dca_request_t
*)ctx
.cc_provider_private
)->dr_flags
356 rv
= dca_3des(&ctx
, input
, output
, req
, mode
);
357 if ((rv
!= CRYPTO_QUEUED
) && (rv
!= CRYPTO_SUCCESS
)) {
358 DBG(NULL
, DWARN
, "dca_3desatomic: dca_3des() failed");
359 output
->cd_length
= 0;
363 * The features of dca_3desfinal() are implemented within
364 * dca_3desdone() due to the asynchronous nature of dca_3des().
368 * The context will be freed in the hardware callback function if it
371 if (rv
!= CRYPTO_QUEUED
)
372 dca_3desctxfree(&ctx
);
378 dca_3desstart(dca_t
*dca
, uint32_t flags
, dca_request_t
*reqp
)
381 crypto_data_t
*in
= reqp
->dr_in
;
383 dca_request_t
*ctx
= reqp
;
388 * 1) in and out point to the "right" buffers.
389 * 2) in->b_bcount - in->b_resid == initial offset
390 * 3) likewise for out
391 * 4) there is enough space in the output
392 * 5) we perform a block for block encrypt
394 len
= ctx
->dr_ctx
.activeresidlen
+ dca_length(in
);
395 len
= ROUNDDOWN(min(len
, MAXPACKET
), DESBLOCK
);
396 reqp
->dr_pkt_length
= (uint16_t)len
;
398 /* collect IVs for this pass */
399 iv
[0] = ctx
->dr_ctx
.iv
[0];
400 iv
[1] = ctx
->dr_ctx
.iv
[1];
403 * And also, for decrypt, collect the IV for the next pass. For
404 * decrypt, the IV must be collected BEFORE decryption, or else
405 * we will lose it. (For encrypt, we grab the IV AFTER encryption,
408 if (flags
& DR_DECRYPT
) {
409 uchar_t ivstore
[DESBLOCK
];
410 #ifdef UNALIGNED_POINTERS_PERMITTED
411 uint32_t *ivp
= (uint32_t *)ivstore
;
413 uchar_t
*ivp
= ivstore
;
414 #endif /* UNALIGNED_POINTERS_PERMITTED */
416 /* get last 8 bytes of ciphertext for IV of next op */
418 * If we're processing only a DESBLOCKS worth of data
419 * and there is active residual present then it will be
420 * needed for the IV also.
422 if ((len
== DESBLOCK
) && ctx
->dr_ctx
.activeresidlen
) {
423 /* Bring the active residual into play */
424 bcopy(ctx
->dr_ctx
.activeresid
, ivstore
,
425 ctx
->dr_ctx
.activeresidlen
);
426 rv
= dca_getbufbytes(in
, 0,
427 DESBLOCK
- ctx
->dr_ctx
.activeresidlen
,
428 ivstore
+ ctx
->dr_ctx
.activeresidlen
);
430 rv
= dca_getbufbytes(in
,
431 len
- DESBLOCK
- ctx
->dr_ctx
.activeresidlen
,
435 if (rv
!= CRYPTO_SUCCESS
) {
437 "dca_3desstart: dca_getbufbytes() failed");
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]);
447 ivp
[0]<<24 | ivp
[1]<<16 | ivp
[2]<<8 | ivp
[3];
449 ivp
[4]<<24 | ivp
[5]<<16 | ivp
[6]<<8 | ivp
[7];
450 #endif /* UNALIGNED_POINTERS_PERMITTED */
453 /* For now we force a pullup. Add direct DMA later. */
454 reqp
->dr_flags
&= ~(DR_SCATTER
| DR_GATHER
);
455 if ((len
< dca_mindma
) || (ctx
->dr_ctx
.activeresidlen
> 0) ||
456 dca_sgcheck(dca
, reqp
->dr_in
, DCA_SG_CONTIG
) ||
457 dca_sgcheck(dca
, reqp
->dr_out
, DCA_SG_WALIGN
)) {
458 reqp
->dr_flags
|= DR_SCATTER
| DR_GATHER
;
461 /* Try to do direct DMA. */
462 if (!(reqp
->dr_flags
& (DR_SCATTER
| DR_GATHER
))) {
463 if (dca_bindchains(reqp
, len
, len
) == DDI_SUCCESS
) {
464 reqp
->dr_in
->cd_offset
+= len
;
465 reqp
->dr_in
->cd_length
-= len
;
468 "dca_3desstart: dca_bindchains() failed");
469 return (CRYPTO_DEVICE_ERROR
);
473 /* gather the data into the device */
474 if (reqp
->dr_flags
& DR_GATHER
) {
475 rv
= dca_resid_gather(in
, (char *)ctx
->dr_ctx
.activeresid
,
476 &ctx
->dr_ctx
.activeresidlen
, reqp
->dr_ibuf_kaddr
, len
);
477 if (rv
!= CRYPTO_SUCCESS
) {
479 "dca_3desstart: dca_resid_gather() failed");
483 * Setup for scattering the result back out
484 * The output buffer is a multi-entry chain for x86 and
485 * a single entry chain for Sparc.
486 * Use the actual length if the first entry is sufficient.
488 (void) ddi_dma_sync(reqp
->dr_ibuf_dmah
, 0, len
,
489 DDI_DMA_SYNC_FORDEV
);
490 if (dca_check_dma_handle(dca
, reqp
->dr_ibuf_dmah
,
491 DCA_FM_ECLASS_NONE
) != DDI_SUCCESS
) {
492 reqp
->destroy
= TRUE
;
493 return (CRYPTO_DEVICE_ERROR
);
496 reqp
->dr_in_paddr
= reqp
->dr_ibuf_head
.dc_buffer_paddr
;
497 reqp
->dr_in_next
= reqp
->dr_ibuf_head
.dc_next_paddr
;
498 if (len
> reqp
->dr_ibuf_head
.dc_buffer_length
)
499 reqp
->dr_in_len
= reqp
->dr_ibuf_head
.dc_buffer_length
;
501 reqp
->dr_in_len
= len
;
504 * Setup for scattering the result back out
505 * The output buffer is a multi-entry chain for x86 and
506 * a single entry chain for Sparc.
507 * Use the actual length if the first entry is sufficient.
509 if (reqp
->dr_flags
& DR_SCATTER
) {
510 reqp
->dr_out_paddr
= reqp
->dr_obuf_head
.dc_buffer_paddr
;
511 reqp
->dr_out_next
= reqp
->dr_obuf_head
.dc_next_paddr
;
512 if (len
> reqp
->dr_obuf_head
.dc_buffer_length
)
513 reqp
->dr_out_len
= reqp
->dr_obuf_head
.dc_buffer_length
;
515 reqp
->dr_out_len
= len
;
518 reqp
->dr_flags
|= flags
;
519 reqp
->dr_callback
= dca_3desdone
;
521 /* write out the context structure */
522 PUTCTX32(reqp
, CTX_3DESIVHI
, iv
[0]);
523 PUTCTX32(reqp
, CTX_3DESIVLO
, iv
[1]);
525 /* schedule the work by doing a submit */
526 return (dca_start(dca
, reqp
, MCR1
, 1));
530 dca_3desdone(dca_request_t
*reqp
, int errno
)
532 crypto_data_t
*out
= reqp
->dr_out
;
533 dca_request_t
*ctx
= reqp
;
536 if (errno
== CRYPTO_SUCCESS
) {
539 * Save the offset: this has to be done *before* dca_scatter
540 * modifies the buffer. We take the initial offset into the
541 * first buf, and add that to the total packet size to find
542 * the end of the packet.
544 off
= dca_length(out
) + reqp
->dr_pkt_length
- DESBLOCK
;
546 if (reqp
->dr_flags
& DR_SCATTER
) {
547 (void) ddi_dma_sync(reqp
->dr_obuf_dmah
, 0,
548 reqp
->dr_out_len
, DDI_DMA_SYNC_FORKERNEL
);
549 if (dca_check_dma_handle(reqp
->dr_dca
,
550 reqp
->dr_obuf_dmah
, DCA_FM_ECLASS_NONE
) !=
552 reqp
->destroy
= TRUE
;
553 errno
= CRYPTO_DEVICE_ERROR
;
557 errno
= dca_scatter(reqp
->dr_obuf_kaddr
,
558 reqp
->dr_out
, reqp
->dr_out_len
, 0);
559 if (errno
!= CRYPTO_SUCCESS
) {
561 "dca_3desdone: dca_scatter() failed");
566 /* we've processed some more data */
567 out
->cd_length
+= reqp
->dr_pkt_length
;
572 * For encryption only, we have to grab the IV for the
573 * next pass AFTER encryption.
575 if (reqp
->dr_flags
& DR_ENCRYPT
) {
576 uchar_t ivstore
[DESBLOCK
];
577 #ifdef UNALIGNED_POINTERS_PERMITTED
578 uint32_t *iv
= (uint32_t *)ivstore
;
580 uchar_t
*iv
= ivstore
;
581 #endif /* UNALIGNED_POINTERS_PERMITTED */
583 /* get last 8 bytes for IV of next op */
584 errno
= dca_getbufbytes(out
, off
, DESBLOCK
,
586 if (errno
!= CRYPTO_SUCCESS
) {
588 "dca_3desdone: dca_getbufbytes() failed");
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]);
598 iv
[0]<<24 | iv
[1]<<16 | iv
[2]<<8 | iv
[3];
600 iv
[4]<<24 | iv
[5]<<16 | iv
[6]<<8 | iv
[7];
601 #endif /* UNALIGNED_POINTERS_PERMITTED */
605 * If there is more to do, then reschedule another
608 if (dca_length(reqp
->dr_in
) >= 8) {
609 errno
= dca_3desstart(reqp
->dr_dca
, reqp
->dr_flags
,
611 if (errno
== CRYPTO_QUEUED
) {
620 * If this is an atomic operation perform the final function
621 * tasks (equivalent to to dca_3desfinal()).
623 if (reqp
->dr_ctx
.atomic
) {
624 if ((errno
== CRYPTO_SUCCESS
) && (ctx
->dr_ctx
.residlen
!= 0)) {
626 "dca_3desdone: invalid nonzero residual");
627 if (reqp
->dr_flags
& DR_DECRYPT
) {
628 errno
= CRYPTO_ENCRYPTED_DATA_LEN_RANGE
;
630 errno
= CRYPTO_DATA_LEN_RANGE
;
635 ASSERT(reqp
->dr_kcf_req
!= NULL
);
636 /* notify framework that request is completed */
637 crypto_op_notification(reqp
->dr_kcf_req
, errno
);
639 "dca_3desdone: returning %d to the kef via crypto_op_notification",
642 /* This has to be done after notifing the framework */
643 if (reqp
->dr_ctx
.atomic
) {
644 reqp
->dr_context
= NULL
;
645 reqp
->dr_ctx
.atomic
= 0;
646 reqp
->dr_ctx
.ctx_cm_type
= 0;
648 dca_destroyreq(reqp
);
656 dca_3desctxinit(crypto_ctx_t
*ctx
, crypto_mechanism_t
*mechanism
,
657 crypto_key_t
*key
, int kmflag
, int flags
)
659 dca_request_t
*des_ctx
;
660 dca_t
*dca
= ctx
->cc_provider
;
661 #ifdef UNALIGNED_POINTERS_PERMITTED
666 #endif /* UNALIGNED_POINTERS_PERMITTED */
672 paramsz
= mechanism
->cm_param_len
;
673 #ifdef UNALIGNED_POINTERS_PERMITTED
674 param
= (uint32_t *)mechanism
->cm_param
;
676 param
= (uchar_t
*)mechanism
->cm_param
;
677 #endif /* UNALIGNED_POINTERS_PERMITTED */
679 if ((paramsz
!= 0) && (paramsz
!= DES_IV_LEN
)) {
681 "dca_3desctxinit: parameter(IV) length not %d (%d)",
682 DES_IV_LEN
, paramsz
);
683 return (CRYPTO_MECHANISM_PARAM_INVALID
);
686 if ((des_ctx
= dca_getreq(dca
, MCR1
, 1)) == NULL
) {
687 dca_error(dca
, "unable to allocate request for 3DES");
688 return (CRYPTO_HOST_MEMORY
);
691 * Identify and store the IV as a pair of native 32-bit words.
693 * If cm_param == NULL then the IV comes from the cd_miscdata field
694 * in the crypto_data structure.
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]);
702 des_ctx
->dr_ctx
.iv
[0] = param
[0]<<24 | param
[1]<<16 |
703 param
[2]<<8 | param
[3];
704 des_ctx
->dr_ctx
.iv
[1] = param
[4]<<24 | param
[5]<<16 |
705 param
[6]<<8 | param
[7];
706 #endif /* UNALIGNED_POINTERS_PERMITTED */
708 des_ctx
->dr_ctx
.residlen
= 0;
709 des_ctx
->dr_ctx
.activeresidlen
= 0;
710 des_ctx
->dr_ctx
.ctx_cm_type
= mechanism
->cm_type
;
711 ctx
->cc_provider_private
= des_ctx
;
713 if (key
->ck_format
!= CRYPTO_KEY_RAW
) {
715 "dca_3desctxinit: only raw crypto key type support with DES/3DES");
716 dca_3desctxfree(ctx
);
717 return (CRYPTO_KEY_TYPE_INCONSISTENT
);
720 len
= key
->ck_length
;
721 value
= (uchar_t
*)key
->ck_data
;
723 if (flags
& DR_TRIPLE
) {
727 for (i
= 0; i
< 6; i
++) {
728 des_ctx
->dr_ctx
.key
[i
] = 0;
729 for (j
= 0; j
< 4; j
++) {
730 des_ctx
->dr_ctx
.key
[i
] <<= 8;
731 des_ctx
->dr_ctx
.key
[i
] |= *value
;
738 for (i
= 0; i
< 4; i
++) {
739 des_ctx
->dr_ctx
.key
[i
] = 0;
740 for (j
= 0; j
< 4; j
++) {
741 des_ctx
->dr_ctx
.key
[i
] <<= 8;
742 des_ctx
->dr_ctx
.key
[i
] |= *value
;
746 des_ctx
->dr_ctx
.key
[4] = des_ctx
->dr_ctx
.key
[0];
747 des_ctx
->dr_ctx
.key
[5] = des_ctx
->dr_ctx
.key
[1];
751 DBG(NULL
, DWARN
, "Incorrect 3DES keysize (%d)", len
);
752 dca_3desctxfree(ctx
);
753 return (CRYPTO_KEY_SIZE_RANGE
);
758 DBG(NULL
, DWARN
, "Incorrect DES keysize (%d)", len
);
759 dca_3desctxfree(ctx
);
760 return (CRYPTO_KEY_SIZE_RANGE
);
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]);
768 des_ctx
->dr_ctx
.key
[0] =
769 value
[0]<<24 | value
[1]<<16 | value
[2]<<8 | value
[3];
770 des_ctx
->dr_ctx
.key
[1] =
771 value
[4]<<24 | value
[5]<<16 | value
[6]<<8 | value
[7];
772 #endif /* UNALIGNED_POINTERS_PERMITTED */
774 /* for single des just repeat des key */
775 des_ctx
->dr_ctx
.key
[4] =
776 des_ctx
->dr_ctx
.key
[2] = des_ctx
->dr_ctx
.key
[0];
777 des_ctx
->dr_ctx
.key
[5] =
778 des_ctx
->dr_ctx
.key
[3] = des_ctx
->dr_ctx
.key
[1];
782 * Setup the context here so that we do not need to setup it up
785 PUTCTX16(des_ctx
, CTX_LENGTH
, CTX_3DES_LENGTH
);
786 PUTCTX16(des_ctx
, CTX_CMD
, CMD_3DES
);
787 PUTCTX32(des_ctx
, CTX_3DESDIRECTION
,
788 flags
& DR_ENCRYPT
? CTX_3DES_ENCRYPT
: CTX_3DES_DECRYPT
);
789 PUTCTX32(des_ctx
, CTX_3DESKEY1HI
, des_ctx
->dr_ctx
.key
[0]);
790 PUTCTX32(des_ctx
, CTX_3DESKEY1LO
, des_ctx
->dr_ctx
.key
[1]);
791 PUTCTX32(des_ctx
, CTX_3DESKEY2HI
, des_ctx
->dr_ctx
.key
[2]);
792 PUTCTX32(des_ctx
, CTX_3DESKEY2LO
, des_ctx
->dr_ctx
.key
[3]);
793 PUTCTX32(des_ctx
, CTX_3DESKEY3HI
, des_ctx
->dr_ctx
.key
[4]);
794 PUTCTX32(des_ctx
, CTX_3DESKEY3LO
, des_ctx
->dr_ctx
.key
[5]);
796 return (CRYPTO_SUCCESS
);