c4f2d992 |
1 | /* -*-c-*- |
2 | * |
c758e654 |
3 | * $Id: icrypt.c,v 1.4 1998/01/12 16:46:02 mdw Exp $ |
c4f2d992 |
4 | * |
9e5602f0 |
5 | * Higher level encryption functions |
c4f2d992 |
6 | * |
c758e654 |
7 | * (c) 1998 Mark Wooding |
c4f2d992 |
8 | */ |
9 | |
03f996bd |
10 | /*----- Licensing notice --------------------------------------------------* |
c4f2d992 |
11 | * |
12 | * This file is part of `become' |
13 | * |
14 | * `Become' is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or |
17 | * (at your option) any later version. |
18 | * |
19 | * `Become' is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. |
23 | * |
24 | * You should have received a copy of the GNU General Public License |
03f996bd |
25 | * along with `become'; if not, write to the Free Software Foundation, |
26 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
c4f2d992 |
27 | */ |
28 | |
29 | /*----- Revision history --------------------------------------------------* |
30 | * |
31 | * $Log: icrypt.c,v $ |
c758e654 |
32 | * Revision 1.4 1998/01/12 16:46:02 mdw |
33 | * Fix copyright date. |
34 | * |
9e5602f0 |
35 | * Revision 1.3 1997/09/26 09:14:58 mdw |
36 | * Merged blowfish branch into trunk. |
37 | * |
38 | * Revision 1.2.2.1 1997/09/26 09:08:07 mdw |
39 | * Use the Blowfish encryption algorithm instead of IDEA. This is partly |
40 | * because I prefer Blowfish (without any particularly strong evidence) but |
41 | * mainly because IDEA is patented and Blowfish isn't. |
42 | * |
03f996bd |
43 | * Revision 1.2 1997/08/04 10:24:22 mdw |
44 | * Sources placed under CVS control. |
45 | * |
46 | * Revision 1.1 1997/07/21 13:47:49 mdw |
c4f2d992 |
47 | * Initial revision |
48 | * |
49 | */ |
50 | |
51 | /*----- Header files ------------------------------------------------------*/ |
52 | |
53 | /* --- ANSI headers --- */ |
54 | |
55 | #include <stdio.h> |
56 | #include <string.h> |
57 | #include <stdlib.h> |
58 | |
59 | /* --- Local headers --- */ |
60 | |
9e5602f0 |
61 | #include "blowfish.h" |
c4f2d992 |
62 | #include "config.h" |
63 | #include "icrypt.h" |
c4f2d992 |
64 | |
65 | /*----- Main code ---------------------------------------------------------*/ |
66 | |
67 | /* --- @icrypt_init@ --- * |
68 | * |
69 | * Arguments: @icrypt_job *j@ = pointer to job context block |
70 | * @unsigned char *k@ = pointer to key data |
9e5602f0 |
71 | * @size_t sz@ = size of the key data |
c4f2d992 |
72 | * @const unsigned char *iv@ = pointer to IV |
73 | * |
74 | * Returns: --- |
75 | * |
76 | * Use: Primes the context block ready for encryption. |
77 | */ |
78 | |
9e5602f0 |
79 | void icrypt_init(icrypt_job *j, unsigned char *k, |
80 | size_t sz, const unsigned char *iv) |
c4f2d992 |
81 | { |
9e5602f0 |
82 | blowfish_setKey(&j->k, k, sz); |
c4f2d992 |
83 | if (iv) |
9e5602f0 |
84 | memcpy(j->iv, iv, BLOWFISH_BLKSIZE); |
c4f2d992 |
85 | else |
9e5602f0 |
86 | memset(j->iv, 0, BLOWFISH_BLKSIZE); |
c4f2d992 |
87 | j->i = 8; |
88 | } |
89 | |
90 | /* --- @icrypt_encrypt@ --- * |
91 | * |
92 | * Arguments: @icrypt_job *j@ = job handle |
93 | * @const void *src@ = pointer to source buffer |
94 | * @void *dest@ = pointer to destination buffer |
95 | * @size_t sz@ = size of buffers to handle |
96 | * |
97 | * Returns: --- |
98 | * |
99 | * Use: Encrypts data from the source to the destination, using the |
100 | * key attached to the job handle. |
101 | */ |
102 | |
103 | void icrypt_encrypt(icrypt_job *j, const void *src, void *dest, size_t sz) |
104 | { |
9e5602f0 |
105 | const unsigned char *s = src; |
106 | unsigned char *d = dest; |
c4f2d992 |
107 | int i; |
108 | |
109 | /* --- First, use up bytes in the buffer --- */ |
110 | |
9e5602f0 |
111 | while (j->i < BLOWFISH_BLKSIZE && sz > 0) { |
c4f2d992 |
112 | *d++ = j->iv[j->i++] ^= *s++; |
113 | sz--; |
114 | } |
115 | if (!sz) return; |
116 | |
117 | /* --- Now encrypt larger chunks at a time --- */ |
118 | |
9e5602f0 |
119 | while (sz >= BLOWFISH_BLKSIZE) { |
c4f2d992 |
120 | |
121 | /* --- Freshen the IV --- */ |
122 | |
9e5602f0 |
123 | blowfish_encrypt(&j->k, j->iv, j->iv); |
c4f2d992 |
124 | |
125 | /* --- Now encrypt some more bytes --- */ |
126 | |
9e5602f0 |
127 | for (i = 0; i < BLOWFISH_BLKSIZE; i++) { |
c4f2d992 |
128 | *d++ = j->iv[i] ^= *s++; |
129 | } |
9e5602f0 |
130 | sz -= BLOWFISH_BLKSIZE; |
c4f2d992 |
131 | } |
132 | if (!sz) return; |
133 | |
134 | /* --- Do the tail-end bits --- */ |
135 | |
9e5602f0 |
136 | blowfish_encrypt(&j->k, j->iv, j->iv); |
c4f2d992 |
137 | j->i = 0; |
138 | while (sz) { |
139 | *d++ = j->iv[j->i++] ^= *s++; |
140 | sz--; |
141 | } |
142 | } |
143 | |
144 | /* --- @icrypt_decrypt@ --- * |
145 | * |
146 | * Arguments: @icrypt_job *j@ = job handle |
147 | * @const void *src@ = pointer to source buffer |
148 | * @void *dest@ = pointer to destination buffer |
149 | * @size_t sz@ = size of buffers to handle |
150 | * |
151 | * Returns: --- |
152 | * |
153 | * Use: Decrypts data from the source to the destination, using |
154 | * the key attached to the job handle. |
155 | */ |
156 | |
157 | void icrypt_decrypt(icrypt_job *j, const void *src, void *dest, size_t sz) |
158 | { |
9e5602f0 |
159 | unsigned const char *s = src; |
160 | unsigned char *d = dest; |
c4f2d992 |
161 | int i; |
9e5602f0 |
162 | unsigned char c; |
c4f2d992 |
163 | |
164 | /* --- First, use up bytes in the buffer --- */ |
165 | |
9e5602f0 |
166 | while (j->i < BLOWFISH_BLKSIZE && sz > 0) { |
c4f2d992 |
167 | c = *s++; |
168 | *d++ = j->iv[j->i] ^ c; |
169 | j->iv[j->i++] = c; |
170 | sz--; |
171 | } |
172 | if (!sz) return; |
173 | |
174 | /* --- Now encrypt larger chunks at a time --- */ |
175 | |
9e5602f0 |
176 | while (sz >= BLOWFISH_BLKSIZE) { |
c4f2d992 |
177 | |
178 | /* --- Freshen the IV --- */ |
179 | |
9e5602f0 |
180 | blowfish_encrypt(&j->k, j->iv, j->iv); |
c4f2d992 |
181 | |
182 | /* --- Now encrypt some more bytes --- */ |
183 | |
9e5602f0 |
184 | for (i = 0; i < BLOWFISH_BLKSIZE; i++) { |
c4f2d992 |
185 | c = *s++; |
186 | *d++ = j->iv[i] ^ c; |
187 | j->iv[i] = c; |
188 | } |
9e5602f0 |
189 | sz -= BLOWFISH_BLKSIZE; |
c4f2d992 |
190 | } |
191 | if (!sz) return; |
192 | |
193 | /* --- Do the tail-end bits --- */ |
194 | |
9e5602f0 |
195 | blowfish_encrypt(&j->k, j->iv, j->iv); |
c4f2d992 |
196 | j->i = 0; |
197 | while (sz) { |
198 | c = *s++; |
199 | *d++ = j->iv[j->i] ^ c; |
200 | j->iv[j->i++] = c; |
201 | sz--; |
202 | } |
203 | } |
204 | |
205 | /* --- @icrypt_reset@ --- * |
206 | * |
207 | * Arguments: @icrypt_job *j@ = pointer to job context block |
208 | * @unsigned char *k@ = pointer to key data, or zero for |
209 | * no change |
9e5602f0 |
210 | * @size_t sz@ = size of the key in bytes |
c4f2d992 |
211 | * @const unsigned char *iv@ = pointer to IV, or zero |
212 | * |
213 | * Returns: --- |
214 | * |
215 | * Use: Alters the context block. This can be used after recovery |
216 | * of a session key, for example. |
217 | */ |
218 | |
9e5602f0 |
219 | void icrypt_reset(icrypt_job *j, unsigned char *k, |
220 | size_t sz, const unsigned char *iv) |
c4f2d992 |
221 | { |
222 | if (k) |
9e5602f0 |
223 | blowfish_setKey(&j->k, k, sz); |
c4f2d992 |
224 | if (iv) |
9e5602f0 |
225 | memcpy(j->iv, iv, BLOWFISH_BLKSIZE); |
c4f2d992 |
226 | else { |
9e5602f0 |
227 | unsigned char b[BLOWFISH_BLKSIZE]; |
228 | int n = j->i, o = BLOWFISH_BLKSIZE - j->i; |
c4f2d992 |
229 | |
230 | memcpy(b, j->iv, sizeof(b)); |
231 | memcpy(j->iv, b + n, o); |
232 | memcpy(j->iv + o, b, n); |
233 | } |
234 | j->i = 8; |
235 | } |
236 | |
237 | /* --- @icrypt_saveIV@ --- * |
238 | * |
239 | * Arguments: @icrypt_job *j@ = pointer to job context block |
240 | * @unsigned char *iv@ = where to store the IV |
241 | * |
242 | * Returns: --- |
243 | * |
244 | * Use: Writes out the job's IV after munging it a little. |
245 | */ |
246 | |
247 | void icrypt_saveIV(icrypt_job *j, unsigned char *iv) |
248 | { |
9e5602f0 |
249 | int n = j->i, o = BLOWFISH_BLKSIZE - j->i; |
c4f2d992 |
250 | |
251 | memcpy(j->iv, iv + n, o); |
252 | memcpy(j->iv + o, iv, n); |
9e5602f0 |
253 | blowfish_encrypt(&j->k, iv, iv); |
c4f2d992 |
254 | } |
255 | |
256 | /*----- Test rig ----------------------------------------------------------*/ |
257 | |
258 | #ifdef TEST_RIG |
259 | |
260 | #include <errno.h> |
261 | #include <pwd.h> |
262 | #include <unistd.h> |
9e5602f0 |
263 | #include "crypt.h" |
c4f2d992 |
264 | #include "mdwopt.h" |
265 | #include "md5.h" |
266 | #include "utils.h" |
267 | |
268 | void icrypt(icrypt_job *j, |
269 | void (*proc)(icrypt_job *j, |
270 | const void *src, |
271 | void *dest, |
272 | size_t sz), |
273 | FILE *fp) |
274 | { |
275 | char buff[71]; |
276 | size_t r; |
277 | |
278 | for (;;) { |
279 | r = fread(buff, 1, sizeof(buff), fp); |
280 | if (!r) break; |
281 | proc(j, buff, buff, r); |
282 | fwrite(buff, 1, r, stdout); |
283 | } |
284 | } |
285 | |
286 | int main(int argc, char *argv[]) |
287 | { |
288 | icrypt_job j; |
289 | md5 md; |
290 | void (*proc)(icrypt_job *j, |
291 | const void *src, |
292 | void *dest, |
293 | size_t sz) = icrypt_encrypt; |
294 | |
295 | ego(argv[0]); |
296 | |
297 | for (;;) { |
298 | int i = getopt(argc, argv, "d"); |
299 | if (i < 0) |
300 | break; |
301 | if (i == 'd') |
302 | proc = icrypt_decrypt; |
303 | } |
304 | |
305 | { |
306 | char *pass = getpass("Password: "); |
9e5602f0 |
307 | unsigned char k[BLOWFISH_KEYSIZE]; |
c4f2d992 |
308 | md5_init(&md); |
309 | md5_buffer(&md, pass, strlen(pass)); |
310 | memset(pass, 0, strlen(pass)); |
03f996bd |
311 | md5_final(&md, k); |
c4f2d992 |
312 | |
9e5602f0 |
313 | icrypt_init(&j, k, BLOWFISH_KEYSIZE, 0); |
c4f2d992 |
314 | } |
315 | |
316 | if (optind >= argc) |
317 | icrypt(&j, proc, stdin); |
318 | |
319 | while (optind < argc) { |
320 | char *p = argv[optind++]; |
321 | if (strcmp(p, "-") == 0) |
322 | icrypt(&j, proc, stdin); |
323 | else { |
324 | FILE *fp = fopen(p, "rb"); |
325 | if (!fp) |
326 | die("couldn't open `%s': %s", p, strerror(errno)); |
327 | icrypt(&j, proc, fp); |
328 | fclose(fp); |
329 | } |
330 | } |
331 | |
332 | return (0); |
333 | } |
334 | |
335 | #endif |
336 | |
337 | /*----- That's all, folks -------------------------------------------------*/ |