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