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