xref: /titanic_41/usr/src/common/net/wanboot/crypt/cbc.c (revision d29b2c4438482eb00488be49a1f5d6835f455546)
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
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
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
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
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