Fix copyright date.
[become] / src / icrypt.c
CommitLineData
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 79void 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
103void 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
157void 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 219void 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
247void 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
268void 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
286int 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 -------------------------------------------------*/