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