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