chiark / gitweb /
Remove `set.c'. No longer necessary.
[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 -------------------------------------------------*/