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 /*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
34 */
35
36 /*
37 * DES encryption library routines
38 */
39
40 #include "mt.h"
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <sys/types.h>
44 #include <rpc/des_crypt.h>
45 #ifdef sun
46 #include <sys/ioctl.h>
47 #include <sys/des.h>
48 #define getdesfd() (open("/dev/des", 0, 0))
49 #else
50 #include <des/des.h>
51 #endif
52 #include <rpc/rpc.h>
53
54 extern int __des_crypt(char *, unsigned, struct desparams *);
55
56 static int common_crypt(char *, char *, unsigned, unsigned, struct desparams *);
57
58 /*
59 * To see if chip is installed
60 */
61 #define UNOPENED (-2)
62 static int g_desfd = UNOPENED;
63
64
65 /*
66 * Copy 8 bytes
67 */
68 #define COPY8(src, dst) { \
69 char *a = (char *)dst; \
70 char *b = (char *)src; \
71 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
72 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
73 }
74
75 /*
76 * Copy multiple of 8 bytes
77 */
78 #define DESCOPY(src, dst, len) { \
79 char *a = (char *)dst; \
80 char *b = (char *)src; \
81 int i; \
82 for (i = (int)len; i > 0; i -= 8) { \
83 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
84 *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
85 } \
86 }
87
88 /*
89 * CBC mode encryption
90 */
91 int
cbc_crypt(char * key,char * buf,size_t len,unsigned int mode,char * ivec)92 cbc_crypt(char *key, char *buf, size_t len, unsigned int mode, char *ivec)
93 {
94 int err;
95 struct desparams dp;
96
97 dp.des_mode = CBC;
98 COPY8(ivec, dp.des_ivec);
99 err = common_crypt(key, buf, len, mode, &dp);
100 COPY8(dp.des_ivec, ivec);
101 return (err);
102 }
103
104
105 /*
106 * ECB mode encryption
107 */
108 int
ecb_crypt(char * key,char * buf,size_t len,unsigned int mode)109 ecb_crypt(char *key, char *buf, size_t len, unsigned int mode)
110 {
111 struct desparams dp;
112
113 dp.des_mode = ECB;
114 return (common_crypt(key, buf, len, mode, &dp));
115 }
116
117
118
119 /*
120 * Common code to cbc_crypt() & ecb_crypt()
121 */
122 static int
common_crypt(char * key,char * buf,unsigned len,unsigned mode,struct desparams * desp)123 common_crypt(char *key, char *buf, unsigned len, unsigned mode,
124 struct desparams *desp)
125 {
126 int desdev;
127 int res;
128
129 if ((len % 8) != 0 || len > DES_MAXDATA)
130 return (DESERR_BADPARAM);
131 desp->des_dir =
132 ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
133
134 desdev = mode & DES_DEVMASK;
135 COPY8(key, desp->des_key);
136 #ifdef sun
137 if (desdev == DES_HW) {
138 if (g_desfd < 0) {
139 if (g_desfd == -1 || (g_desfd = getdesfd()) < 0) {
140 goto software; /* no hardware device */
141 }
142 }
143
144 /*
145 * hardware
146 */
147 desp->des_len = len;
148 if (len <= DES_QUICKLEN) {
149 DESCOPY(buf, desp->des_data, len);
150 res = ioctl(g_desfd, DESIOCQUICK, (char *)desp);
151 DESCOPY(desp->des_data, buf, len);
152 } else {
153 desp->des_buf = (uchar_t *)buf;
154 res = ioctl(g_desfd, DESIOCBLOCK, (char *)desp);
155 }
156 return (res == 0 ? DESERR_NONE : DESERR_HWERROR);
157 }
158 software:
159 #endif
160 /*
161 * software
162 */
163 if (!__des_crypt(buf, len, desp))
164 return (DESERR_HWERROR);
165 return (desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
166 }
167
168 static int
desN_crypt(des_block keys[],int keynum,char * buf,unsigned int len,unsigned int mode,char * ivec)169 desN_crypt(des_block keys[], int keynum, char *buf, unsigned int len,
170 unsigned int mode, char *ivec)
171 {
172 unsigned int m = mode & (DES_ENCRYPT | DES_DECRYPT);
173 unsigned int flags = mode & ~(DES_ENCRYPT | DES_DECRYPT);
174 des_block svec, dvec;
175 int i, j, stat;
176
177 if (keynum < 1)
178 return (DESERR_BADPARAM);
179
180 (void) memcpy(svec.c, ivec, sizeof (des_block));
181 for (i = 0; i < keynum; i++) {
182 j = (mode & DES_DECRYPT) ? keynum - 1 - i : i;
183 stat = cbc_crypt(keys[j].c, buf, len, m | flags, ivec);
184 if (mode & DES_DECRYPT && i == 0)
185 (void) memcpy(dvec.c, ivec, sizeof (des_block));
186
187 if (DES_FAILED(stat))
188 return (stat);
189
190 m = (m == DES_ENCRYPT ? DES_DECRYPT : DES_ENCRYPT);
191
192 if ((mode & DES_DECRYPT) || i != keynum - 1 || i%2)
193 (void) memcpy(ivec, svec.c, sizeof (des_block));
194 }
195 if (keynum % 2 == 0)
196 stat = cbc_crypt(keys[0].c, buf, len, mode, ivec);
197
198 if (mode & DES_DECRYPT)
199 (void) memcpy(ivec, dvec.c, sizeof (des_block));
200
201 return (stat);
202 }
203
204
205
206 int
__cbc_triple_crypt(des_block keys[],char * buf,uint_t len,uint_t mode,char * ivec)207 __cbc_triple_crypt(des_block keys[], char *buf, uint_t len,
208 uint_t mode, char *ivec)
209 {
210 return (desN_crypt(keys, 3, buf, len, mode, ivec));
211 }
212