xref: /titanic_53/usr/src/common/crypto/modes/ecb.c (revision 23c57df72989c916b3e98084eb88d48777999691)
1*23c57df7Smcpowers /*
2*23c57df7Smcpowers  * CDDL HEADER START
3*23c57df7Smcpowers  *
4*23c57df7Smcpowers  * The contents of this file are subject to the terms of the
5*23c57df7Smcpowers  * Common Development and Distribution License (the "License").
6*23c57df7Smcpowers  * You may not use this file except in compliance with the License.
7*23c57df7Smcpowers  *
8*23c57df7Smcpowers  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*23c57df7Smcpowers  * or http://www.opensolaris.org/os/licensing.
10*23c57df7Smcpowers  * See the License for the specific language governing permissions
11*23c57df7Smcpowers  * and limitations under the License.
12*23c57df7Smcpowers  *
13*23c57df7Smcpowers  * When distributing Covered Code, include this CDDL HEADER in each
14*23c57df7Smcpowers  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*23c57df7Smcpowers  * If applicable, add the following below this CDDL HEADER, with the
16*23c57df7Smcpowers  * fields enclosed by brackets "[]" replaced with your own identifying
17*23c57df7Smcpowers  * information: Portions Copyright [yyyy] [name of copyright owner]
18*23c57df7Smcpowers  *
19*23c57df7Smcpowers  * CDDL HEADER END
20*23c57df7Smcpowers  */
21*23c57df7Smcpowers /*
22*23c57df7Smcpowers  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*23c57df7Smcpowers  * Use is subject to license terms.
24*23c57df7Smcpowers  */
25*23c57df7Smcpowers 
26*23c57df7Smcpowers #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*23c57df7Smcpowers 
28*23c57df7Smcpowers #ifndef _KERNEL
29*23c57df7Smcpowers #include <strings.h>
30*23c57df7Smcpowers #include <limits.h>
31*23c57df7Smcpowers #include <assert.h>
32*23c57df7Smcpowers #include <security/cryptoki.h>
33*23c57df7Smcpowers #endif
34*23c57df7Smcpowers 
35*23c57df7Smcpowers #include <sys/types.h>
36*23c57df7Smcpowers #include <modes/modes.h>
37*23c57df7Smcpowers #include <sys/crypto/common.h>
38*23c57df7Smcpowers #include <sys/crypto/impl.h>
39*23c57df7Smcpowers 
40*23c57df7Smcpowers /*
41*23c57df7Smcpowers  * Algorithm independent ECB functions.
42*23c57df7Smcpowers  */
43*23c57df7Smcpowers int
44*23c57df7Smcpowers ecb_cipher_contiguous_blocks(ecb_ctx_t *ctx, char *data, size_t length,
45*23c57df7Smcpowers     crypto_data_t *out, size_t block_size,
46*23c57df7Smcpowers     int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct))
47*23c57df7Smcpowers {
48*23c57df7Smcpowers 	size_t remainder = length;
49*23c57df7Smcpowers 	size_t need;
50*23c57df7Smcpowers 	uint8_t *datap = (uint8_t *)data;
51*23c57df7Smcpowers 	uint8_t *blockp;
52*23c57df7Smcpowers 	uint8_t *lastp;
53*23c57df7Smcpowers 	void *iov_or_mp;
54*23c57df7Smcpowers 	offset_t offset;
55*23c57df7Smcpowers 	uint8_t *out_data_1;
56*23c57df7Smcpowers 	uint8_t *out_data_2;
57*23c57df7Smcpowers 	size_t out_data_1_len;
58*23c57df7Smcpowers 
59*23c57df7Smcpowers 	if (length + ctx->cc_remainder_len < block_size) {
60*23c57df7Smcpowers 		/* accumulate bytes here and return */
61*23c57df7Smcpowers 		bcopy(datap,
62*23c57df7Smcpowers 		    (uint8_t *)ctx->cc_remainder + ctx->cc_remainder_len,
63*23c57df7Smcpowers 		    length);
64*23c57df7Smcpowers 		ctx->cc_remainder_len += length;
65*23c57df7Smcpowers 		ctx->cc_copy_to = datap;
66*23c57df7Smcpowers 		return (CRYPTO_SUCCESS);
67*23c57df7Smcpowers 	}
68*23c57df7Smcpowers 
69*23c57df7Smcpowers 	lastp = (uint8_t *)ctx->cc_iv;
70*23c57df7Smcpowers 	if (out != NULL)
71*23c57df7Smcpowers 		crypto_init_ptrs(out, &iov_or_mp, &offset);
72*23c57df7Smcpowers 
73*23c57df7Smcpowers 	do {
74*23c57df7Smcpowers 		/* Unprocessed data from last call. */
75*23c57df7Smcpowers 		if (ctx->cc_remainder_len > 0) {
76*23c57df7Smcpowers 			need = block_size - ctx->cc_remainder_len;
77*23c57df7Smcpowers 
78*23c57df7Smcpowers 			if (need > remainder)
79*23c57df7Smcpowers 				return (CRYPTO_DATA_LEN_RANGE);
80*23c57df7Smcpowers 
81*23c57df7Smcpowers 			bcopy(datap, &((uint8_t *)ctx->cc_remainder)
82*23c57df7Smcpowers 			    [ctx->cc_remainder_len], need);
83*23c57df7Smcpowers 
84*23c57df7Smcpowers 			blockp = (uint8_t *)ctx->cc_remainder;
85*23c57df7Smcpowers 		} else {
86*23c57df7Smcpowers 			blockp = datap;
87*23c57df7Smcpowers 		}
88*23c57df7Smcpowers 
89*23c57df7Smcpowers 		if (out == NULL) {
90*23c57df7Smcpowers 			cipher(ctx->cc_keysched, blockp, blockp);
91*23c57df7Smcpowers 
92*23c57df7Smcpowers 			ctx->cc_lastp = blockp;
93*23c57df7Smcpowers 			lastp = blockp;
94*23c57df7Smcpowers 
95*23c57df7Smcpowers 			if (ctx->cc_remainder_len > 0) {
96*23c57df7Smcpowers 				bcopy(blockp, ctx->cc_copy_to,
97*23c57df7Smcpowers 				    ctx->cc_remainder_len);
98*23c57df7Smcpowers 				bcopy(blockp + ctx->cc_remainder_len, datap,
99*23c57df7Smcpowers 				    need);
100*23c57df7Smcpowers 			}
101*23c57df7Smcpowers 		} else {
102*23c57df7Smcpowers 			cipher(ctx->cc_keysched, blockp, lastp);
103*23c57df7Smcpowers 			crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
104*23c57df7Smcpowers 			    &out_data_1_len, &out_data_2, block_size);
105*23c57df7Smcpowers 
106*23c57df7Smcpowers 			/* copy block to where it belongs */
107*23c57df7Smcpowers 			bcopy(lastp, out_data_1, out_data_1_len);
108*23c57df7Smcpowers 			if (out_data_2 != NULL) {
109*23c57df7Smcpowers 				bcopy(lastp + out_data_1_len, out_data_2,
110*23c57df7Smcpowers 				    block_size - out_data_1_len);
111*23c57df7Smcpowers 			}
112*23c57df7Smcpowers 			/* update offset */
113*23c57df7Smcpowers 			out->cd_offset += block_size;
114*23c57df7Smcpowers 		}
115*23c57df7Smcpowers 
116*23c57df7Smcpowers 		/* Update pointer to next block of data to be processed. */
117*23c57df7Smcpowers 		if (ctx->cc_remainder_len != 0) {
118*23c57df7Smcpowers 			datap += need;
119*23c57df7Smcpowers 			ctx->cc_remainder_len = 0;
120*23c57df7Smcpowers 		} else {
121*23c57df7Smcpowers 			datap += block_size;
122*23c57df7Smcpowers 		}
123*23c57df7Smcpowers 
124*23c57df7Smcpowers 		remainder = (size_t)&data[length] - (size_t)datap;
125*23c57df7Smcpowers 
126*23c57df7Smcpowers 		/* Incomplete last block. */
127*23c57df7Smcpowers 		if (remainder > 0 && remainder < block_size) {
128*23c57df7Smcpowers 			bcopy(datap, ctx->cc_remainder, remainder);
129*23c57df7Smcpowers 			ctx->cc_remainder_len = remainder;
130*23c57df7Smcpowers 			ctx->cc_copy_to = datap;
131*23c57df7Smcpowers 			goto out;
132*23c57df7Smcpowers 		}
133*23c57df7Smcpowers 		ctx->cc_copy_to = NULL;
134*23c57df7Smcpowers 
135*23c57df7Smcpowers 	} while (remainder > 0);
136*23c57df7Smcpowers 
137*23c57df7Smcpowers out:
138*23c57df7Smcpowers 	return (CRYPTO_SUCCESS);
139*23c57df7Smcpowers }
140*23c57df7Smcpowers 
141*23c57df7Smcpowers /* ARGSUSED */
142*23c57df7Smcpowers void *
143*23c57df7Smcpowers ecb_alloc_ctx(int kmflag)
144*23c57df7Smcpowers {
145*23c57df7Smcpowers 	ecb_ctx_t *ecb_ctx;
146*23c57df7Smcpowers 
147*23c57df7Smcpowers #ifdef _KERNEL
148*23c57df7Smcpowers 	if ((ecb_ctx = kmem_zalloc(sizeof (ecb_ctx_t), kmflag)) == NULL)
149*23c57df7Smcpowers #else
150*23c57df7Smcpowers 	if ((ecb_ctx = calloc(1, sizeof (ecb_ctx_t))) == NULL)
151*23c57df7Smcpowers #endif
152*23c57df7Smcpowers 		return (NULL);
153*23c57df7Smcpowers 
154*23c57df7Smcpowers 	ecb_ctx->cc_flags = ECB_MODE;
155*23c57df7Smcpowers 	return (ecb_ctx);
156*23c57df7Smcpowers }
157