3 * $Id: icrypt.c,v 1.4 1998/01/12 16:46:02 mdw Exp $
5 * Higher level encryption functions
7 * (c) 1998 Mark Wooding
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of `become'
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.
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.
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.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.4 1998/01/12 16:46:02 mdw
35 * Revision 1.3 1997/09/26 09:14:58 mdw
36 * Merged blowfish branch into trunk.
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.
43 * Revision 1.2 1997/08/04 10:24:22 mdw
44 * Sources placed under CVS control.
46 * Revision 1.1 1997/07/21 13:47:49 mdw
51 /*----- Header files ------------------------------------------------------*/
53 /* --- ANSI headers --- */
59 /* --- Local headers --- */
65 /*----- Main code ---------------------------------------------------------*/
67 /* --- @icrypt_init@ --- *
69 * Arguments: @icrypt_job *j@ = pointer to job context block
70 * @unsigned char *k@ = pointer to key data
71 * @size_t sz@ = size of the key data
72 * @const unsigned char *iv@ = pointer to IV
76 * Use: Primes the context block ready for encryption.
79 void icrypt_init(icrypt_job
*j
, unsigned char *k
,
80 size_t sz
, const unsigned char *iv
)
82 blowfish_setKey(&j
->k
, k
, sz
);
84 memcpy(j
->iv
, iv
, BLOWFISH_BLKSIZE
);
86 memset(j
->iv
, 0, BLOWFISH_BLKSIZE
);
90 /* --- @icrypt_encrypt@ --- *
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
99 * Use: Encrypts data from the source to the destination, using the
100 * key attached to the job handle.
103 void icrypt_encrypt(icrypt_job
*j
, const void *src
, void *dest
, size_t sz
)
105 const unsigned char *s
= src
;
106 unsigned char *d
= dest
;
109 /* --- First, use up bytes in the buffer --- */
111 while (j
->i
< BLOWFISH_BLKSIZE
&& sz
> 0) {
112 *d
++ = j
->iv
[j
->i
++] ^= *s
++;
117 /* --- Now encrypt larger chunks at a time --- */
119 while (sz
>= BLOWFISH_BLKSIZE
) {
121 /* --- Freshen the IV --- */
123 blowfish_encrypt(&j
->k
, j
->iv
, j
->iv
);
125 /* --- Now encrypt some more bytes --- */
127 for (i
= 0; i
< BLOWFISH_BLKSIZE
; i
++) {
128 *d
++ = j
->iv
[i
] ^= *s
++;
130 sz
-= BLOWFISH_BLKSIZE
;
134 /* --- Do the tail-end bits --- */
136 blowfish_encrypt(&j
->k
, j
->iv
, j
->iv
);
139 *d
++ = j
->iv
[j
->i
++] ^= *s
++;
144 /* --- @icrypt_decrypt@ --- *
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
153 * Use: Decrypts data from the source to the destination, using
154 * the key attached to the job handle.
157 void icrypt_decrypt(icrypt_job
*j
, const void *src
, void *dest
, size_t sz
)
159 unsigned const char *s
= src
;
160 unsigned char *d
= dest
;
164 /* --- First, use up bytes in the buffer --- */
166 while (j
->i
< BLOWFISH_BLKSIZE
&& sz
> 0) {
168 *d
++ = j
->iv
[j
->i
] ^ c
;
174 /* --- Now encrypt larger chunks at a time --- */
176 while (sz
>= BLOWFISH_BLKSIZE
) {
178 /* --- Freshen the IV --- */
180 blowfish_encrypt(&j
->k
, j
->iv
, j
->iv
);
182 /* --- Now encrypt some more bytes --- */
184 for (i
= 0; i
< BLOWFISH_BLKSIZE
; i
++) {
189 sz
-= BLOWFISH_BLKSIZE
;
193 /* --- Do the tail-end bits --- */
195 blowfish_encrypt(&j
->k
, j
->iv
, j
->iv
);
199 *d
++ = j
->iv
[j
->i
] ^ c
;
205 /* --- @icrypt_reset@ --- *
207 * Arguments: @icrypt_job *j@ = pointer to job context block
208 * @unsigned char *k@ = pointer to key data, or zero for
210 * @size_t sz@ = size of the key in bytes
211 * @const unsigned char *iv@ = pointer to IV, or zero
215 * Use: Alters the context block. This can be used after recovery
216 * of a session key, for example.
219 void icrypt_reset(icrypt_job
*j
, unsigned char *k
,
220 size_t sz
, const unsigned char *iv
)
223 blowfish_setKey(&j
->k
, k
, sz
);
225 memcpy(j
->iv
, iv
, BLOWFISH_BLKSIZE
);
227 unsigned char b
[BLOWFISH_BLKSIZE
];
228 int n
= j
->i
, o
= BLOWFISH_BLKSIZE
- j
->i
;
230 memcpy(b
, j
->iv
, sizeof(b
));
231 memcpy(j
->iv
, b
+ n
, o
);
232 memcpy(j
->iv
+ o
, b
, n
);
237 /* --- @icrypt_saveIV@ --- *
239 * Arguments: @icrypt_job *j@ = pointer to job context block
240 * @unsigned char *iv@ = where to store the IV
244 * Use: Writes out the job's IV after munging it a little.
247 void icrypt_saveIV(icrypt_job
*j
, unsigned char *iv
)
249 int n
= j
->i
, o
= BLOWFISH_BLKSIZE
- j
->i
;
251 memcpy(j
->iv
, iv
+ n
, o
);
252 memcpy(j
->iv
+ o
, iv
, n
);
253 blowfish_encrypt(&j
->k
, iv
, iv
);
256 /*----- Test rig ----------------------------------------------------------*/
268 void icrypt(icrypt_job
*j
,
269 void (*proc
)(icrypt_job
*j
,
279 r
= fread(buff
, 1, sizeof(buff
), fp
);
281 proc(j
, buff
, buff
, r
);
282 fwrite(buff
, 1, r
, stdout
);
286 int main(int argc
, char *argv
[])
290 void (*proc
)(icrypt_job
*j
,
293 size_t sz
) = icrypt_encrypt
;
298 int i
= getopt(argc
, argv
, "d");
302 proc
= icrypt_decrypt
;
306 char *pass
= getpass("Password: ");
307 unsigned char k
[BLOWFISH_KEYSIZE
];
309 md5_buffer(&md
, pass
, strlen(pass
));
310 memset(pass
, 0, strlen(pass
));
313 icrypt_init(&j
, k
, BLOWFISH_KEYSIZE
, 0);
317 icrypt(&j
, proc
, stdin
);
319 while (optind
< argc
) {
320 char *p
= argv
[optind
++];
321 if (strcmp(p
, "-") == 0)
322 icrypt(&j
, proc
, stdin
);
324 FILE *fp
= fopen(p
, "rb");
326 die("couldn't open `%s': %s", p
, strerror(errno
));
327 icrypt(&j
, proc
, fp
);
337 /*----- That's all, folks -------------------------------------------------*/