1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/sysmacros.h>
30 #if defined(_KERNEL) && !defined(_BOOT)
31 #include <sys/systm.h>
32 #else
33 #include <strings.h>
34 #endif
35 #include "cbc.h"
36
37 #define CBC_MAX_BLOCK_SIZE 64
38
39 static void
cbc_xorblock(uint8_t * lastp,uint8_t * thisp,int blocksize)40 cbc_xorblock(uint8_t *lastp, uint8_t *thisp, int blocksize)
41 {
42 uint32_t *this32p;
43 uint32_t *last32p;
44 int i;
45
46 if (IS_P2ALIGNED(thisp, sizeof (uint32_t)) &&
47 IS_P2ALIGNED(lastp, sizeof (uint32_t)) &&
48 IS_P2ALIGNED(blocksize, sizeof (uint32_t))) {
49 /* LINTED */
50 this32p = (uint32_t *)thisp;
51 /* LINTED */
52 last32p = (uint32_t *)lastp;
53 for (i = 0; i < blocksize; i += 4) {
54 *this32p ^= *last32p;
55 this32p++;
56 last32p++;
57 }
58 } else {
59 for (i = 0; i < blocksize; i++) {
60 thisp[i] ^= lastp[i];
61 }
62 }
63 }
64
65 boolean_t
cbc_encrypt(cbc_handle_t * ch,uint8_t * data,size_t datalen,uint8_t * IV)66 cbc_encrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen,
67 uint8_t *IV)
68 {
69 uint8_t *lastp;
70 uint8_t *thisp;
71 size_t i;
72
73 if (!IS_P2ALIGNED(datalen, ch->blocklen)) {
74 return (B_FALSE);
75 }
76
77 thisp = data;
78 lastp = IV;
79
80 for (i = 0; i < datalen; i += ch->blocklen) {
81 cbc_xorblock(lastp, thisp, ch->blocklen);
82 /* Encrypt the current block. */
83 ch->encrypt(ch->ks, thisp);
84 lastp = thisp;
85 thisp += ch->blocklen;
86 }
87
88 bcopy(lastp, IV, ch->blocklen);
89 return (B_TRUE);
90 }
91
92 boolean_t
cbc_decrypt(cbc_handle_t * ch,uint8_t * data,size_t datalen,uint8_t * IV)93 cbc_decrypt(cbc_handle_t *ch, uint8_t *data, size_t datalen,
94 uint8_t *IV)
95 {
96 uint8_t cbcblock[CBC_MAX_BLOCK_SIZE];
97 uint8_t *lastp;
98 uint8_t *thisp;
99 size_t i;
100
101 if (!IS_P2ALIGNED(datalen, ch->blocklen)) {
102 return (B_FALSE);
103 }
104
105 thisp = data;
106 lastp = IV;
107
108 for (i = 0; i < datalen; i += ch->blocklen) {
109
110 /* Copy the current ciphertext block. */
111 bcopy(thisp, cbcblock, ch->blocklen);
112
113 /* Decrypt the current block. */
114 ch->decrypt(ch->ks, thisp);
115
116 cbc_xorblock(lastp, thisp, ch->blocklen);
117
118 /* Save the last ciphertext block. */
119 bcopy(cbcblock, lastp, ch->blocklen);
120 thisp += ch->blocklen;
121 }
122
123 return (B_TRUE);
124 }
125
126 void
cbc_makehandle(cbc_handle_t * ch,void * cookie,uint32_t keysize,uint32_t blocksize,uint32_t ivsize,void (* encrypt)(void *,uint8_t *),void (* decrypt)(void *,uint8_t *))127 cbc_makehandle(cbc_handle_t *ch, void *cookie, uint32_t keysize,
128 uint32_t blocksize, uint32_t ivsize,
129 void (*encrypt)(void *, uint8_t *),
130 void (*decrypt)(void *, uint8_t *))
131 {
132 ch->ks = cookie;
133 ch->keylen = keysize;
134 ch->blocklen = blocksize;
135 ch->ivlen = ivsize;
136 ch->encrypt = encrypt;
137 ch->decrypt = decrypt;
138 }
139