summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2002-02-19 15:26:42 +1100
committerDamien Miller <djm@mindrot.org>2002-02-19 15:26:42 +1100
commit21cf4e0628bc5b372e002916f8b2020d98524a35 (patch)
tree8335027111f526af8de872d47cc2fc1a1082a569
parenta93c6d87ef75a23cfbdb30f0a5821ae54300895f (diff)
- markus@cvs.openbsd.org 2002/02/18 13:05:32
[cipher.c cipher.h] switch to EVP, ok djm@ deraadt@
-rw-r--r--ChangeLog5
-rw-r--r--cipher.c683
-rw-r--r--cipher.h38
3 files changed, 320 insertions, 406 deletions
diff --git a/ChangeLog b/ChangeLog
index 35a73574e..4b7dcca64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -34,6 +34,9 @@
34 [auth.h] 34 [auth.h]
35 Manual cleanup of remaining userland __P use (excluding packages 35 Manual cleanup of remaining userland __P use (excluding packages
36 maintained outside the tree) 36 maintained outside the tree)
37 - markus@cvs.openbsd.org 2002/02/18 13:05:32
38 [cipher.c cipher.h]
39 switch to EVP, ok djm@ deraadt@
37 40
3820020218 4120020218
39 - (tim) newer config.guess from ftp://ftp.gnu.org/gnu/config/config.guess 42 - (tim) newer config.guess from ftp://ftp.gnu.org/gnu/config/config.guess
@@ -7631,4 +7634,4 @@
7631 - Wrote replacements for strlcpy and mkdtemp 7634 - Wrote replacements for strlcpy and mkdtemp
7632 - Released 1.0pre1 7635 - Released 1.0pre1
7633 7636
7634$Id: ChangeLog,v 1.1862 2002/02/19 04:25:29 djm Exp $ 7637$Id: ChangeLog,v 1.1863 2002/02/19 04:26:42 djm Exp $
diff --git a/cipher.c b/cipher.c
index c31696cee..ce3f6f3ce 100644
--- a/cipher.c
+++ b/cipher.c
@@ -35,386 +35,50 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: cipher.c,v 1.51 2002/02/14 23:41:01 markus Exp $"); 38RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "log.h" 41#include "log.h"
42#include "cipher.h" 42#include "cipher.h"
43 43
44#include <openssl/md5.h> 44#include <openssl/md5.h>
45#include "rijndael.h"
46
47static EVP_CIPHER *evp_ssh1_3des(void);
48static EVP_CIPHER *evp_ssh1_bf(void);
49static EVP_CIPHER *evp_rijndael(void);
45 50
46struct Cipher { 51struct Cipher {
47 char *name; 52 char *name;
48 int number; /* for ssh1 only */ 53 int number; /* for ssh1 only */
49 u_int block_size; 54 u_int block_size;
50 u_int key_len; 55 u_int key_len;
51 void (*setkey)(CipherContext *, const u_char *, u_int); 56 EVP_CIPHER *(*evptype)(void);
52 void (*setiv)(CipherContext *, const u_char *, u_int); 57} ciphers[] = {
53 void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int); 58 { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
54 void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int); 59 { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
55}; 60 { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
56 61 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
57/* no encryption */ 62
58static void 63 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
59none_setkey(CipherContext *cc, const u_char *key, u_int keylen) 64 { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
60{ 65 { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
61} 66 { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
62static void 67 { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
63none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) 68 { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
64{ 69 { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
65} 70
66static void 71 { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
67none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
68{
69 memcpy(dest, src, len);
70}
71
72/* DES */
73static void
74des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
75{
76 static int dowarn = 1;
77 if (dowarn) {
78 error("Warning: use of DES is strongly discouraged "
79 "due to cryptographic weaknesses");
80 dowarn = 0;
81 }
82 des_set_key((void *)key, cc->u.des.key);
83}
84static void
85des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
86{
87 memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));
88}
89static void
90des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
91{
92 des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
93 DES_ENCRYPT);
94}
95static void
96des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
97{
98 des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
99 DES_DECRYPT);
100}
101
102/* 3DES */
103static void
104des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)
105{
106 des_set_key((void *) key, cc->u.des3.key1);
107 des_set_key((void *) (key+8), cc->u.des3.key2);
108 des_set_key((void *) (key+16), cc->u.des3.key3);
109}
110static void
111des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
112{
113 memset(cc->u.des3.iv1, 0, sizeof(cc->u.des3.iv1));
114 memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));
115 memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));
116 if (iv == NULL)
117 return;
118 memcpy(cc->u.des3.iv3, (char *)iv, 8);
119}
120static void
121des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
122{
123 des_ede3_cbc_encrypt(src, dest, len,
124 cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
125 &cc->u.des3.iv3, DES_ENCRYPT);
126}
127static void
128des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
129{
130 des_ede3_cbc_encrypt(src, dest, len,
131 cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
132 &cc->u.des3.iv3, DES_DECRYPT);
133}
134
135/*
136 * This is used by SSH1:
137 *
138 * What kind of triple DES are these 2 routines?
139 *
140 * Why is there a redundant initialization vector?
141 *
142 * If only iv3 was used, then, this would till effect have been
143 * outer-cbc. However, there is also a private iv1 == iv2 which
144 * perhaps makes differential analysis easier. On the other hand, the
145 * private iv1 probably makes the CRC-32 attack ineffective. This is a
146 * result of that there is no longer any known iv1 to use when
147 * choosing the X block.
148 */
149static void
150des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
151{
152 des_set_key((void *) key, cc->u.des3.key1);
153 des_set_key((void *) (key+8), cc->u.des3.key2);
154 if (keylen <= 16)
155 des_set_key((void *) key, cc->u.des3.key3);
156 else
157 des_set_key((void *) (key+16), cc->u.des3.key3);
158}
159static void
160des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
161 u_int len)
162{
163 des_ncbc_encrypt(src, dest, len, cc->u.des3.key1, &cc->u.des3.iv1,
164 DES_ENCRYPT);
165 des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2,
166 DES_DECRYPT);
167 des_ncbc_encrypt(dest, dest, len, cc->u.des3.key3, &cc->u.des3.iv3,
168 DES_ENCRYPT);
169}
170static void
171des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
172 u_int len)
173{
174 des_ncbc_encrypt(src, dest, len, cc->u.des3.key3, &cc->u.des3.iv3,
175 DES_DECRYPT);
176 des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2,
177 DES_ENCRYPT);
178 des_ncbc_encrypt(dest, dest, len, cc->u.des3.key1, &cc->u.des3.iv1,
179 DES_DECRYPT);
180}
181
182/* Blowfish */
183static void
184blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
185{
186 BF_set_key(&cc->u.bf.key, keylen, (u_char *)key);
187}
188static void
189blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
190{
191 if (iv == NULL)
192 memset(cc->u.bf.iv, 0, 8);
193 else
194 memcpy(cc->u.bf.iv, (char *)iv, 8);
195}
196static void
197blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
198 u_int len)
199{
200 BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
201 BF_ENCRYPT);
202}
203static void
204blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
205 u_int len)
206{
207 BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
208 BF_DECRYPT);
209}
210
211/*
212 * SSH1 uses a variation on Blowfish, all bytes must be swapped before
213 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
214 */
215static void
216swap_bytes(const u_char *src, u_char *dst, int n)
217{
218 char c[4];
219
220 /* Process 4 bytes every lap. */
221 for (n = n / 4; n > 0; n--) {
222 c[3] = *src++;
223 c[2] = *src++;
224 c[1] = *src++;
225 c[0] = *src++;
226
227 *dst++ = c[0];
228 *dst++ = c[1];
229 *dst++ = c[2];
230 *dst++ = c[3];
231 }
232}
233
234static void
235blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
236 u_int len)
237{
238 swap_bytes(src, dest, len);
239 BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
240 BF_ENCRYPT);
241 swap_bytes(dest, dest, len);
242}
243static void
244blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
245 u_int len)
246{
247 swap_bytes(src, dest, len);
248 BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
249 BF_DECRYPT);
250 swap_bytes(dest, dest, len);
251}
252
253/* alleged rc4 */
254static void
255arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)
256{
257 RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);
258}
259static void
260arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
261{
262 RC4(&cc->u.rc4, len, (u_char *)src, dest);
263}
264
265/* CAST */
266static void
267cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
268{
269 CAST_set_key(&cc->u.cast.key, keylen, (u_char *) key);
270}
271static void
272cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
273{
274 if (iv == NULL)
275 fatal("no IV for %s.", cc->cipher->name);
276 memcpy(cc->u.cast.iv, (char *)iv, 8);
277}
278static void
279cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
280{
281 CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
282 CAST_ENCRYPT);
283}
284static void
285cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
286{
287 CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
288 CAST_DECRYPT);
289}
290
291/* RIJNDAEL */
292
293#define RIJNDAEL_BLOCKSIZE 16
294static void
295rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)
296{
297 rijndael_set_key(&cc->u.rijndael.enc, (char *)key, 8*keylen, 1);
298 rijndael_set_key(&cc->u.rijndael.dec, (char *)key, 8*keylen, 0);
299}
300static void
301rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
302{
303 if (iv == NULL || ivlen != RIJNDAEL_BLOCKSIZE)
304 fatal("bad/no IV for %s.", cc->cipher->name);
305 memcpy(cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
306}
307static void
308rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
309 u_int len)
310{
311 rijndael_ctx *ctx = &cc->u.rijndael.enc;
312 u_char *iv = cc->u.rijndael.iv;
313 u_char in[RIJNDAEL_BLOCKSIZE];
314 u_char *cprev, *cnow, *plain;
315 int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
316
317 if (len == 0)
318 return;
319 if (len % RIJNDAEL_BLOCKSIZE)
320 fatal("rijndael_cbc_encrypt: bad len %d", len);
321 cnow = dest;
322 plain = (u_char *)src;
323 cprev = iv;
324 for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
325 cnow+=RIJNDAEL_BLOCKSIZE) {
326 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
327 in[j] = plain[j] ^ cprev[j];
328 rijndael_encrypt(ctx, in, cnow);
329 cprev = cnow;
330 }
331 memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE);
332}
333static void
334rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
335 u_int len)
336{
337 rijndael_ctx *ctx = &cc->u.rijndael.dec;
338 u_char *iv = cc->u.rijndael.iv;
339 u_char ivsaved[RIJNDAEL_BLOCKSIZE];
340 u_char *cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
341 u_char *plain = dest+len-RIJNDAEL_BLOCKSIZE;
342 u_char *ivp;
343 int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
344
345 if (len == 0)
346 return;
347 if (len % RIJNDAEL_BLOCKSIZE)
348 fatal("rijndael_cbc_decrypt: bad len %d", len);
349 memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE);
350 for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
351 plain-=RIJNDAEL_BLOCKSIZE) {
352 rijndael_decrypt(ctx, cnow, plain);
353 ivp = (i == 1) ? iv : cnow-RIJNDAEL_BLOCKSIZE;
354 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
355 plain[j] ^= ivp[j];
356 }
357 memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE);
358}
359
360Cipher ciphers[] = {
361 { "none",
362 SSH_CIPHER_NONE, 8, 0,
363 none_setkey, none_setiv,
364 none_crypt, none_crypt },
365 { "des",
366 SSH_CIPHER_DES, 8, 8,
367 des_ssh1_setkey, des_ssh1_setiv,
368 des_ssh1_encrypt, des_ssh1_decrypt },
369 { "3des",
370 SSH_CIPHER_3DES, 8, 16,
371 des3_ssh1_setkey, des3_setiv,
372 des3_ssh1_encrypt, des3_ssh1_decrypt },
373 { "blowfish",
374 SSH_CIPHER_BLOWFISH, 8, 16,
375 blowfish_setkey, blowfish_setiv,
376 blowfish_ssh1_encrypt, blowfish_ssh1_decrypt },
377
378 { "3des-cbc",
379 SSH_CIPHER_SSH2, 8, 24,
380 des3_setkey, des3_setiv,
381 des3_cbc_encrypt, des3_cbc_decrypt },
382 { "blowfish-cbc",
383 SSH_CIPHER_SSH2, 8, 16,
384 blowfish_setkey, blowfish_setiv,
385 blowfish_cbc_encrypt, blowfish_cbc_decrypt },
386 { "cast128-cbc",
387 SSH_CIPHER_SSH2, 8, 16,
388 cast_setkey, cast_setiv,
389 cast_cbc_encrypt, cast_cbc_decrypt },
390 { "arcfour",
391 SSH_CIPHER_SSH2, 8, 16,
392 arcfour_setkey, none_setiv,
393 arcfour_crypt, arcfour_crypt },
394 { "aes128-cbc",
395 SSH_CIPHER_SSH2, 16, 16,
396 rijndael_setkey, rijndael_setiv,
397 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
398 { "aes192-cbc",
399 SSH_CIPHER_SSH2, 16, 24,
400 rijndael_setkey, rijndael_setiv,
401 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
402 { "aes256-cbc",
403 SSH_CIPHER_SSH2, 16, 32,
404 rijndael_setkey, rijndael_setiv,
405 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
406 { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
407}; 72};
408 73
409/*--*/ 74/*--*/
410 75
411u_int 76u_int
412cipher_blocksize(Cipher *c) 77cipher_blocksize(Cipher *c)
413{ 78{
414 return (c->block_size); 79 return (c->block_size);
415} 80}
416 81u_int
417u_int
418cipher_keylen(Cipher *c) 82cipher_keylen(Cipher *c)
419{ 83{
420 return (c->key_len); 84 return (c->key_len);
@@ -502,9 +166,25 @@ cipher_name(int id)
502} 166}
503 167
504void 168void
505cipher_init(CipherContext *cc, Cipher *cipher, const u_char *key, 169cipher_init(CipherContext *cc, Cipher *cipher,
506 u_int keylen, const u_char *iv, u_int ivlen, int encrypt) 170 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
171 int encrypt)
507{ 172{
173 static int dowarn = 1;
174 const EVP_CIPHER *type;
175 int klen;
176
177 if (cipher->number == SSH_CIPHER_DES) {
178 if (dowarn) {
179 error("Warning: use of DES is strongly discouraged "
180 "due to cryptographic weaknesses");
181 dowarn = 0;
182 }
183 if (keylen > 8)
184 keylen = 8;
185 }
186 cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
187
508 if (keylen < cipher->key_len) 188 if (keylen < cipher->key_len)
509 fatal("cipher_init: key length %d is insufficient for %s.", 189 fatal("cipher_init: key length %d is insufficient for %s.",
510 keylen, cipher->name); 190 keylen, cipher->name);
@@ -512,9 +192,24 @@ cipher_init(CipherContext *cc, Cipher *cipher, const u_char *key,
512 fatal("cipher_init: iv length %d is insufficient for %s.", 192 fatal("cipher_init: iv length %d is insufficient for %s.",
513 ivlen, cipher->name); 193 ivlen, cipher->name);
514 cc->cipher = cipher; 194 cc->cipher = cipher;
515 cc->encrypt = (encrypt == CIPHER_ENCRYPT); 195
516 cipher->setkey(cc, key, keylen); 196 type = (*cipher->evptype)();
517 cipher->setiv(cc, iv, ivlen); 197
198 EVP_CIPHER_CTX_init(&cc->evp);
199 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
200 (encrypt == CIPHER_ENCRYPT)) == 0)
201 fatal("cipher_init: EVP_CipherInit failed for %s",
202 cipher->name);
203 klen = EVP_CIPHER_CTX_key_length(&cc->evp);
204 if (klen > 0 && keylen != klen) {
205 debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
206 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
207 fatal("cipher_init: set keylen failed (%d -> %d)",
208 klen, keylen);
209 }
210 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
211 fatal("cipher_init: EVP_CipherInit: set key failed for %s",
212 cipher->name);
518} 213}
519 214
520void 215void
@@ -522,16 +217,15 @@ cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
522{ 217{
523 if (len % cc->cipher->block_size) 218 if (len % cc->cipher->block_size)
524 fatal("cipher_encrypt: bad plaintext length %d", len); 219 fatal("cipher_encrypt: bad plaintext length %d", len);
525 if (cc->encrypt) 220 if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
526 cc->cipher->encrypt(cc, dest, src, len); 221 fatal("evp_crypt: EVP_Cipher failed");
527 else
528 cc->cipher->decrypt(cc, dest, src, len);
529} 222}
530 223
531void 224void
532cipher_cleanup(CipherContext *cc) 225cipher_cleanup(CipherContext *cc)
533{ 226{
534 memset(cc, 0, sizeof(*cc)); 227 if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
228 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
535} 229}
536 230
537/* 231/*
@@ -555,3 +249,252 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher,
555 memset(digest, 0, sizeof(digest)); 249 memset(digest, 0, sizeof(digest));
556 memset(&md, 0, sizeof(md)); 250 memset(&md, 0, sizeof(md));
557} 251}
252
253/* Implementations for other non-EVP ciphers */
254
255/*
256 * This is used by SSH1:
257 *
258 * What kind of triple DES are these 2 routines?
259 *
260 * Why is there a redundant initialization vector?
261 *
262 * If only iv3 was used, then, this would till effect have been
263 * outer-cbc. However, there is also a private iv1 == iv2 which
264 * perhaps makes differential analysis easier. On the other hand, the
265 * private iv1 probably makes the CRC-32 attack ineffective. This is a
266 * result of that there is no longer any known iv1 to use when
267 * choosing the X block.
268 */
269struct ssh1_3des_ctx
270{
271 EVP_CIPHER_CTX k1, k2, k3;
272};
273static int
274ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
275 int enc)
276{
277 struct ssh1_3des_ctx *c;
278 u_char *k1, *k2, *k3;
279
280 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
281 c = xmalloc(sizeof(*c));
282 EVP_CIPHER_CTX_set_app_data(ctx, c);
283 }
284 if (key == NULL)
285 return (1);
286 if (enc == -1)
287 enc = ctx->encrypt;
288 k1 = k2 = k3 = (u_char *) key;
289 k2 += 8;
290 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
291 if (enc)
292 k3 += 16;
293 else
294 k1 += 16;
295 }
296 EVP_CIPHER_CTX_init(&c->k1);
297 EVP_CIPHER_CTX_init(&c->k2);
298 EVP_CIPHER_CTX_init(&c->k3);
299 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
300 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
301 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
302 memset(c, 0, sizeof(*c));
303 xfree(c);
304 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
305 return (0);
306 }
307 return (1);
308}
309static int
310ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
311{
312 struct ssh1_3des_ctx *c;
313
314 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
315 error("ssh1_3des_cbc: no context");
316 return (0);
317 }
318 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
319 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
320 EVP_Cipher(&c->k3, dest, dest, len) == 0)
321 return (0);
322 return (1);
323}
324static int
325ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
326{
327 struct ssh1_3des_ctx *c;
328
329 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
330 memset(c, 0, sizeof(*c));
331 xfree(c);
332 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
333 }
334 return (1);
335}
336static EVP_CIPHER *
337evp_ssh1_3des(void)
338{
339 static EVP_CIPHER ssh1_3des;
340
341 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
342 ssh1_3des.nid = NID_undef;
343 ssh1_3des.block_size = 8;
344 ssh1_3des.iv_len = 0;
345 ssh1_3des.key_len = 16;
346 ssh1_3des.init = ssh1_3des_init;
347 ssh1_3des.cleanup = ssh1_3des_cleanup;
348 ssh1_3des.do_cipher = ssh1_3des_cbc;
349 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
350 return (&ssh1_3des);
351}
352
353/*
354 * SSH1 uses a variation on Blowfish, all bytes must be swapped before
355 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
356 */
357static void
358swap_bytes(const u_char *src, u_char *dst, int n)
359{
360 u_char c[4];
361
362 /* Process 4 bytes every lap. */
363 for (n = n / 4; n > 0; n--) {
364 c[3] = *src++;
365 c[2] = *src++;
366 c[1] = *src++;
367 c[0] = *src++;
368
369 *dst++ = c[0];
370 *dst++ = c[1];
371 *dst++ = c[2];
372 *dst++ = c[3];
373 }
374}
375static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
376static int
377bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
378{
379 int ret;
380
381 swap_bytes(in, out, len);
382 ret = (*orig_bf)(ctx, out, out, len);
383 swap_bytes(out, out, len);
384 return (ret);
385}
386static EVP_CIPHER *
387evp_ssh1_bf(void)
388{
389 static EVP_CIPHER ssh1_bf;
390
391 memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
392 orig_bf = ssh1_bf.do_cipher;
393 ssh1_bf.nid = NID_undef;
394 ssh1_bf.do_cipher = bf_ssh1_cipher;
395 ssh1_bf.key_len = 32;
396 return (&ssh1_bf);
397}
398
399/* RIJNDAEL */
400#define RIJNDAEL_BLOCKSIZE 16
401struct ssh_rijndael_ctx
402{
403 rijndael_ctx r_ctx;
404 u_char r_iv[RIJNDAEL_BLOCKSIZE];
405};
406
407static int
408ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
409 int enc)
410{
411 struct ssh_rijndael_ctx *c;
412
413 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
414 c = xmalloc(sizeof(*c));
415 EVP_CIPHER_CTX_set_app_data(ctx, c);
416 }
417 if (key != NULL) {
418 if (enc == -1)
419 enc = ctx->encrypt;
420 rijndael_set_key(&c->r_ctx, (u_char *)key,
421 8*EVP_CIPHER_CTX_key_length(ctx), enc);
422 }
423 if (iv != NULL)
424 memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
425 return (1);
426}
427static int
428ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
429 u_int len)
430{
431 struct ssh_rijndael_ctx *c;
432 u_char buf[RIJNDAEL_BLOCKSIZE];
433 u_char *cprev, *cnow, *plain, *ivp;
434 int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
435
436 if (len == 0)
437 return (1);
438 if (len % RIJNDAEL_BLOCKSIZE)
439 fatal("ssh_rijndael_cbc: bad len %d", len);
440 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
441 error("ssh_rijndael_cbc: no context");
442 return (0);
443 }
444 if (ctx->encrypt) {
445 cnow = dest;
446 plain = (u_char *)src;
447 cprev = c->r_iv;
448 for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
449 cnow+=RIJNDAEL_BLOCKSIZE) {
450 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
451 buf[j] = plain[j] ^ cprev[j];
452 rijndael_encrypt(&c->r_ctx, buf, cnow);
453 cprev = cnow;
454 }
455 memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
456 } else {
457 cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
458 plain = dest+len-RIJNDAEL_BLOCKSIZE;
459
460 memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
461 for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
462 plain-=RIJNDAEL_BLOCKSIZE) {
463 rijndael_decrypt(&c->r_ctx, cnow, plain);
464 ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
465 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
466 plain[j] ^= ivp[j];
467 }
468 memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
469 }
470 return (1);
471}
472static int
473ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
474{
475 struct ssh_rijndael_ctx *c;
476
477 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
478 memset(c, 0, sizeof(*c));
479 xfree(c);
480 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
481 }
482 return (1);
483}
484static EVP_CIPHER *
485evp_rijndael(void)
486{
487 static EVP_CIPHER rijndal_cbc;
488
489 memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
490 rijndal_cbc.nid = NID_undef;
491 rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
492 rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
493 rijndal_cbc.key_len = 16;
494 rijndal_cbc.init = ssh_rijndael_init;
495 rijndal_cbc.cleanup = ssh_rijndael_cleanup;
496 rijndal_cbc.do_cipher = ssh_rijndael_cbc;
497 rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
498 EVP_CIPH_ALWAYS_CALL_INIT;
499 return (&rijndal_cbc);
500}
diff --git a/cipher.h b/cipher.h
index 0c412b47f..b800c9614 100644
--- a/cipher.h
+++ b/cipher.h
@@ -32,16 +32,12 @@
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35/* RCSID("$OpenBSD: cipher.h,v 1.30 2002/02/14 23:41:01 markus Exp $"); */ 35/* RCSID("$OpenBSD: cipher.h,v 1.31 2002/02/18 13:05:32 markus Exp $"); */
36 36
37#ifndef CIPHER_H 37#ifndef CIPHER_H
38#define CIPHER_H 38#define CIPHER_H
39 39
40#include <openssl/des.h> 40#include <openssl/evp.h>
41#include <openssl/blowfish.h>
42#include <openssl/rc4.h>
43#include <openssl/cast.h>
44#include "rijndael.h"
45/* 41/*
46 * Cipher types for SSH-1. New types can be added, but old types should not 42 * Cipher types for SSH-1. New types can be added, but old types should not
47 * be removed for compatibility. The maximum allowed value is 31. 43 * be removed for compatibility. The maximum allowed value is 31.
@@ -67,36 +63,8 @@ typedef struct CipherContext CipherContext;
67 63
68struct Cipher; 64struct Cipher;
69struct CipherContext { 65struct CipherContext {
70 union {
71 struct {
72 des_key_schedule key;
73 des_cblock iv;
74 } des;
75 struct {
76 des_key_schedule key1;
77 des_key_schedule key2;
78 des_key_schedule key3;
79 des_cblock iv1;
80 des_cblock iv2;
81 des_cblock iv3;
82 } des3;
83 struct {
84 struct bf_key_st key;
85 u_char iv[8];
86 } bf;
87 struct {
88 CAST_KEY key;
89 u_char iv[8];
90 } cast;
91 struct {
92 u_char iv[16];
93 rijndael_ctx enc;
94 rijndael_ctx dec;
95 } rijndael;
96 RC4_KEY rc4;
97 } u;
98 int plaintext; 66 int plaintext;
99 int encrypt; 67 EVP_CIPHER_CTX evp;
100 Cipher *cipher; 68 Cipher *cipher;
101}; 69};
102 70