]> andersk Git - openssh.git/blame - cipher.c
- markus@cvs.openbsd.org 2002/05/15 21:56:38
[openssh.git] / cipher.c
CommitLineData
8efc0c15 1/*
5260325f 2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
5260325f 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
6ae2364d 5 *
bcbf86ec 6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 *
13 * Copyright (c) 1999 Niels Provos. All rights reserved.
a96070d4 14 * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved.
bcbf86ec 15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
6ae2364d 24 *
bcbf86ec 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5260325f 35 */
8efc0c15 36
37#include "includes.h"
bf03f2da 38RCSID("$OpenBSD: cipher.c,v 1.55 2002/04/03 09:26:11 markus Exp $");
8efc0c15 39
a8be9f80 40#include "xmalloc.h"
42f11eb2 41#include "log.h"
42#include "cipher.h"
8efc0c15 43
44#include <openssl/md5.h>
70fc1609 45#include "rijndael.h"
46
a068d86f 47#if OPENSSL_VERSION_NUMBER < 0x00906000L
48#define SSH_OLD_EVP
49#define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data)
50#endif
51
70fc1609 52static EVP_CIPHER *evp_ssh1_3des(void);
53static EVP_CIPHER *evp_ssh1_bf(void);
54static EVP_CIPHER *evp_rijndael(void);
8efc0c15 55
3ee832e5 56struct Cipher {
57 char *name;
58 int number; /* for ssh1 only */
59 u_int block_size;
60 u_int key_len;
70fc1609 61 EVP_CIPHER *(*evptype)(void);
62} ciphers[] = {
63 { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
64 { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
65 { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
66 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
67
68 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
69 { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
70 { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
71 { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
72 { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
73 { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
74 { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
bf03f2da 75 { "rijndael-cbc@lysator.liu.se",
76 SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
70fc1609 77
78 { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
94ec8c6b 79};
80
81/*--*/
82
762715ce 83u_int
3ee832e5 84cipher_blocksize(Cipher *c)
85{
86 return (c->block_size);
87}
762715ce 88u_int
3ee832e5 89cipher_keylen(Cipher *c)
90{
91 return (c->key_len);
92}
762715ce 93u_int
bf8269a9 94cipher_get_number(Cipher *c)
95{
96 return (c->number);
97}
3ee832e5 98
1e3b8b07 99u_int
94ec8c6b 100cipher_mask_ssh1(int client)
8ce64345 101{
1e3b8b07 102 u_int mask = 0;
184eed6a 103 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
94ec8c6b 104 mask |= 1 << SSH_CIPHER_BLOWFISH;
105 if (client) {
106 mask |= 1 << SSH_CIPHER_DES;
107 }
5260325f 108 return mask;
8efc0c15 109}
94ec8c6b 110
111Cipher *
112cipher_by_name(const char *name)
8ce64345 113{
94ec8c6b 114 Cipher *c;
115 for (c = ciphers; c->name != NULL; c++)
116 if (strcasecmp(c->name, name) == 0)
117 return c;
118 return NULL;
8ce64345 119}
8efc0c15 120
94ec8c6b 121Cipher *
122cipher_by_number(int id)
8efc0c15 123{
94ec8c6b 124 Cipher *c;
125 for (c = ciphers; c->name != NULL; c++)
126 if (c->number == id)
127 return c;
128 return NULL;
8efc0c15 129}
130
a8be9f80 131#define CIPHER_SEP ","
132int
133ciphers_valid(const char *names)
134{
94ec8c6b 135 Cipher *c;
089fbbd2 136 char *ciphers, *cp;
a8be9f80 137 char *p;
a8be9f80 138
71276795 139 if (names == NULL || strcmp(names, "") == 0)
a8be9f80 140 return 0;
089fbbd2 141 ciphers = cp = xstrdup(names);
94ec8c6b 142 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
184eed6a 143 (p = strsep(&cp, CIPHER_SEP))) {
94ec8c6b 144 c = cipher_by_name(p);
145 if (c == NULL || c->number != SSH_CIPHER_SSH2) {
146 debug("bad cipher %s [%s]", p, names);
a8be9f80 147 xfree(ciphers);
148 return 0;
94ec8c6b 149 } else {
33de75a3 150 debug3("cipher ok: %s [%s]", p, names);
a8be9f80 151 }
152 }
33de75a3 153 debug3("ciphers ok: [%s]", names);
a8be9f80 154 xfree(ciphers);
155 return 1;
156}
157
aa3378df 158/*
159 * Parses the name of the cipher. Returns the number of the corresponding
160 * cipher, or -1 on error.
161 */
8efc0c15 162
163int
164cipher_number(const char *name)
165{
94ec8c6b 166 Cipher *c;
71276795 167 if (name == NULL)
168 return -1;
94ec8c6b 169 c = cipher_by_name(name);
170 return (c==NULL) ? -1 : c->number;
171}
172
173char *
174cipher_name(int id)
175{
176 Cipher *c = cipher_by_number(id);
177 return (c==NULL) ? "<unknown>" : c->name;
178}
179
180void
70fc1609 181cipher_init(CipherContext *cc, Cipher *cipher,
182 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
183 int encrypt)
94ec8c6b 184{
70fc1609 185 static int dowarn = 1;
a068d86f 186#ifdef SSH_OLD_EVP
187 EVP_CIPHER *type;
188#else
70fc1609 189 const EVP_CIPHER *type;
a068d86f 190#endif
70fc1609 191 int klen;
192
193 if (cipher->number == SSH_CIPHER_DES) {
194 if (dowarn) {
195 error("Warning: use of DES is strongly discouraged "
196 "due to cryptographic weaknesses");
197 dowarn = 0;
198 }
199 if (keylen > 8)
200 keylen = 8;
201 }
202 cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
203
94ec8c6b 204 if (keylen < cipher->key_len)
205 fatal("cipher_init: key length %d is insufficient for %s.",
206 keylen, cipher->name);
207 if (iv != NULL && ivlen < cipher->block_size)
208 fatal("cipher_init: iv length %d is insufficient for %s.",
209 ivlen, cipher->name);
210 cc->cipher = cipher;
70fc1609 211
212 type = (*cipher->evptype)();
213
214 EVP_CIPHER_CTX_init(&cc->evp);
a068d86f 215#ifdef SSH_OLD_EVP
216 if (type->key_len > 0 && type->key_len != keylen) {
217 debug("cipher_init: set keylen (%d -> %d)",
218 type->key_len, keylen);
219 type->key_len = keylen;
220 }
221 EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
222 (encrypt == CIPHER_ENCRYPT));
223#else
70fc1609 224 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
225 (encrypt == CIPHER_ENCRYPT)) == 0)
226 fatal("cipher_init: EVP_CipherInit failed for %s",
227 cipher->name);
228 klen = EVP_CIPHER_CTX_key_length(&cc->evp);
229 if (klen > 0 && keylen != klen) {
230 debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
231 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
232 fatal("cipher_init: set keylen failed (%d -> %d)",
233 klen, keylen);
234 }
235 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
236 fatal("cipher_init: EVP_CipherInit: set key failed for %s",
237 cipher->name);
a068d86f 238#endif
94ec8c6b 239}
240
241void
3ee832e5 242cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
94ec8c6b 243{
244 if (len % cc->cipher->block_size)
245 fatal("cipher_encrypt: bad plaintext length %d", len);
a068d86f 246#ifdef SSH_OLD_EVP
247 EVP_Cipher(&cc->evp, dest, (u_char *)src, len);
248#else
70fc1609 249 if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
250 fatal("evp_crypt: EVP_Cipher failed");
a068d86f 251#endif
94ec8c6b 252}
253
254void
3ee832e5 255cipher_cleanup(CipherContext *cc)
94ec8c6b 256{
a068d86f 257#ifdef SSH_OLD_EVP
258 EVP_CIPHER_CTX_cleanup(&cc->evp);
259#else
70fc1609 260 if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
261 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
a068d86f 262#endif
8efc0c15 263}
264
aa3378df 265/*
266 * Selects the cipher, and keys if by computing the MD5 checksum of the
267 * passphrase and using the resulting 16 bytes as the key.
268 */
8efc0c15 269
6ae2364d 270void
94ec8c6b 271cipher_set_key_string(CipherContext *cc, Cipher *cipher,
3ee832e5 272 const char *passphrase, int encrypt)
8efc0c15 273{
5260325f 274 MD5_CTX md;
1e3b8b07 275 u_char digest[16];
5260325f 276
277 MD5_Init(&md);
94ec8c6b 278 MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
5260325f 279 MD5_Final(digest, &md);
280
3ee832e5 281 cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
5260325f 282
283 memset(digest, 0, sizeof(digest));
284 memset(&md, 0, sizeof(md));
8efc0c15 285}
70fc1609 286
287/* Implementations for other non-EVP ciphers */
288
289/*
290 * This is used by SSH1:
291 *
292 * What kind of triple DES are these 2 routines?
293 *
294 * Why is there a redundant initialization vector?
295 *
296 * If only iv3 was used, then, this would till effect have been
297 * outer-cbc. However, there is also a private iv1 == iv2 which
298 * perhaps makes differential analysis easier. On the other hand, the
299 * private iv1 probably makes the CRC-32 attack ineffective. This is a
300 * result of that there is no longer any known iv1 to use when
301 * choosing the X block.
302 */
303struct ssh1_3des_ctx
304{
305 EVP_CIPHER_CTX k1, k2, k3;
306};
307static int
308ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
309 int enc)
310{
311 struct ssh1_3des_ctx *c;
312 u_char *k1, *k2, *k3;
313
314 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
315 c = xmalloc(sizeof(*c));
316 EVP_CIPHER_CTX_set_app_data(ctx, c);
317 }
318 if (key == NULL)
319 return (1);
320 if (enc == -1)
321 enc = ctx->encrypt;
322 k1 = k2 = k3 = (u_char *) key;
323 k2 += 8;
324 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
325 if (enc)
326 k3 += 16;
327 else
328 k1 += 16;
329 }
330 EVP_CIPHER_CTX_init(&c->k1);
331 EVP_CIPHER_CTX_init(&c->k2);
332 EVP_CIPHER_CTX_init(&c->k3);
a068d86f 333#ifdef SSH_OLD_EVP
334 EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
335 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
336 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
337#else
70fc1609 338 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
339 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
340 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
341 memset(c, 0, sizeof(*c));
342 xfree(c);
343 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
344 return (0);
345 }
a068d86f 346#endif
70fc1609 347 return (1);
348}
349static int
350ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
351{
352 struct ssh1_3des_ctx *c;
353
354 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
355 error("ssh1_3des_cbc: no context");
356 return (0);
357 }
a068d86f 358#ifdef SSH_OLD_EVP
359 EVP_Cipher(&c->k1, dest, (u_char *)src, len);
360 EVP_Cipher(&c->k2, dest, dest, len);
361 EVP_Cipher(&c->k3, dest, dest, len);
362#else
70fc1609 363 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
364 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
365 EVP_Cipher(&c->k3, dest, dest, len) == 0)
366 return (0);
a068d86f 367#endif
70fc1609 368 return (1);
369}
370static int
371ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
372{
373 struct ssh1_3des_ctx *c;
374
375 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
376 memset(c, 0, sizeof(*c));
377 xfree(c);
378 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
379 }
380 return (1);
381}
382static EVP_CIPHER *
383evp_ssh1_3des(void)
384{
385 static EVP_CIPHER ssh1_3des;
386
387 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
388 ssh1_3des.nid = NID_undef;
389 ssh1_3des.block_size = 8;
390 ssh1_3des.iv_len = 0;
391 ssh1_3des.key_len = 16;
392 ssh1_3des.init = ssh1_3des_init;
393 ssh1_3des.cleanup = ssh1_3des_cleanup;
394 ssh1_3des.do_cipher = ssh1_3des_cbc;
a068d86f 395#ifndef SSH_OLD_EVP
70fc1609 396 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
a068d86f 397#endif
70fc1609 398 return (&ssh1_3des);
399}
400
401/*
402 * SSH1 uses a variation on Blowfish, all bytes must be swapped before
403 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
404 */
405static void
406swap_bytes(const u_char *src, u_char *dst, int n)
407{
408 u_char c[4];
409
410 /* Process 4 bytes every lap. */
411 for (n = n / 4; n > 0; n--) {
412 c[3] = *src++;
413 c[2] = *src++;
414 c[1] = *src++;
415 c[0] = *src++;
416
417 *dst++ = c[0];
418 *dst++ = c[1];
419 *dst++ = c[2];
420 *dst++ = c[3];
421 }
422}
423static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
424static int
425bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
426{
427 int ret;
428
429 swap_bytes(in, out, len);
430 ret = (*orig_bf)(ctx, out, out, len);
431 swap_bytes(out, out, len);
432 return (ret);
433}
434static EVP_CIPHER *
435evp_ssh1_bf(void)
436{
437 static EVP_CIPHER ssh1_bf;
438
439 memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
440 orig_bf = ssh1_bf.do_cipher;
441 ssh1_bf.nid = NID_undef;
442 ssh1_bf.do_cipher = bf_ssh1_cipher;
443 ssh1_bf.key_len = 32;
444 return (&ssh1_bf);
445}
446
447/* RIJNDAEL */
448#define RIJNDAEL_BLOCKSIZE 16
449struct ssh_rijndael_ctx
450{
451 rijndael_ctx r_ctx;
452 u_char r_iv[RIJNDAEL_BLOCKSIZE];
453};
454
455static int
456ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
457 int enc)
458{
459 struct ssh_rijndael_ctx *c;
460
461 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
462 c = xmalloc(sizeof(*c));
463 EVP_CIPHER_CTX_set_app_data(ctx, c);
464 }
465 if (key != NULL) {
466 if (enc == -1)
467 enc = ctx->encrypt;
468 rijndael_set_key(&c->r_ctx, (u_char *)key,
469 8*EVP_CIPHER_CTX_key_length(ctx), enc);
470 }
471 if (iv != NULL)
472 memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
473 return (1);
474}
475static int
476ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
477 u_int len)
478{
479 struct ssh_rijndael_ctx *c;
480 u_char buf[RIJNDAEL_BLOCKSIZE];
481 u_char *cprev, *cnow, *plain, *ivp;
482 int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
483
484 if (len == 0)
485 return (1);
486 if (len % RIJNDAEL_BLOCKSIZE)
487 fatal("ssh_rijndael_cbc: bad len %d", len);
488 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
489 error("ssh_rijndael_cbc: no context");
490 return (0);
491 }
492 if (ctx->encrypt) {
493 cnow = dest;
494 plain = (u_char *)src;
495 cprev = c->r_iv;
496 for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
497 cnow+=RIJNDAEL_BLOCKSIZE) {
498 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
499 buf[j] = plain[j] ^ cprev[j];
500 rijndael_encrypt(&c->r_ctx, buf, cnow);
501 cprev = cnow;
502 }
503 memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
504 } else {
505 cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
506 plain = dest+len-RIJNDAEL_BLOCKSIZE;
507
508 memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
509 for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
510 plain-=RIJNDAEL_BLOCKSIZE) {
511 rijndael_decrypt(&c->r_ctx, cnow, plain);
05976246 512 ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
513 for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
514 plain[j] ^= ivp[j];
515 }
516 memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
517 }
518 return (1);
519}
520static int
521ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
522{
523 struct ssh_rijndael_ctx *c;
524
525 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
526 memset(c, 0, sizeof(*c));
527 xfree(c);
528 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
529 }
530 return (1);
531}
532static EVP_CIPHER *
533evp_rijndael(void)
534{
535 static EVP_CIPHER rijndal_cbc;
536
537 memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
538 rijndal_cbc.nid = NID_undef;
539 rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
540 rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
541 rijndal_cbc.key_len = 16;
542 rijndal_cbc.init = ssh_rijndael_init;
543 rijndal_cbc.cleanup = ssh_rijndael_cleanup;
544 rijndal_cbc.do_cipher = ssh_rijndael_cbc;
545#ifndef SSH_OLD_EVP
546 rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
547 EVP_CIPH_ALWAYS_CALL_INIT;
548#endif
549 return (&rijndal_cbc);
bf8269a9 550}
551
762715ce 552/*
bf8269a9 553 * Exports an IV from the CipherContext required to export the key
554 * state back from the unprivileged child to the privileged parent
555 * process.
556 */
557
558int
559cipher_get_keyiv_len(CipherContext *cc)
560{
561 Cipher *c = cc->cipher;
562 int ivlen;
563
564 if (c->number == SSH_CIPHER_3DES)
565 ivlen = 24;
566 else
567 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
568 return (ivlen);
569}
570
571void
572cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
573{
574 Cipher *c = cc->cipher;
575 u_char *civ = NULL;
576 int evplen;
577
578 switch (c->number) {
579 case SSH_CIPHER_SSH2:
580 case SSH_CIPHER_DES:
581 case SSH_CIPHER_BLOWFISH:
582 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
583 if (evplen == 0)
584 return;
585 if (evplen != len)
586 fatal("%s: wrong iv length %d != %d", __FUNCTION__,
587 evplen, len);
588
bf03f2da 589 if (c->evptype == evp_rijndael) {
bf8269a9 590 struct ssh_rijndael_ctx *aesc;
591
592 aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
593 if (aesc == NULL)
594 fatal("%s: no rijndael context", __FUNCTION__);
595 civ = aesc->r_iv;
596 } else {
597 civ = cc->evp.iv;
598 }
599 break;
600 case SSH_CIPHER_3DES: {
601 struct ssh1_3des_ctx *desc;
602 if (len != 24)
603 fatal("%s: bad 3des iv length: %d", __FUNCTION__, len);
604 desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
605 if (desc == NULL)
606 fatal("%s: no 3des context", __FUNCTION__);
607 debug3("%s: Copying 3DES IV", __FUNCTION__);
608 memcpy(iv, desc->k1.iv, 8);
609 memcpy(iv + 8, desc->k2.iv, 8);
610 memcpy(iv + 16, desc->k3.iv, 8);
611 return;
612 }
613 default:
614 fatal("%s: bad cipher %d", __FUNCTION__, c->number);
615 }
616 memcpy(iv, civ, len);
617}
618
619void
620cipher_set_keyiv(CipherContext *cc, u_char *iv)
621{
622 Cipher *c = cc->cipher;
623 u_char *div = NULL;
624 int evplen = 0;
625
626 switch (c->number) {
627 case SSH_CIPHER_SSH2:
628 case SSH_CIPHER_DES:
629 case SSH_CIPHER_BLOWFISH:
630 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
631 if (evplen == 0)
632 return;
633
bf03f2da 634 if (c->evptype == evp_rijndael) {
bf8269a9 635 struct ssh_rijndael_ctx *aesc;
636
637 aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
638 if (aesc == NULL)
639 fatal("%s: no rijndael context", __FUNCTION__);
640 div = aesc->r_iv;
641 }else {
642 div = cc->evp.iv;
643 }
644 break;
645 case SSH_CIPHER_3DES: {
646 struct ssh1_3des_ctx *desc;
647 desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
648 if (desc == NULL)
649 fatal("%s: no 3des context", __FUNCTION__);
650 debug3("%s: Installed 3DES IV", __FUNCTION__);
651 memcpy(desc->k1.iv, iv, 8);
652 memcpy(desc->k2.iv, iv + 8, 8);
653 memcpy(desc->k3.iv, iv + 16, 8);
654 return;
762715ce 655 }
bf8269a9 656 default:
657 fatal("%s: bad cipher %d", __FUNCTION__, c->number);
658 }
659 memcpy(div, iv, evplen);
660}
661
662#if OPENSSL_VERSION_NUMBER < 0x00907000L
663#define EVP_X_STATE(evp) &(evp).c
664#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
665#else
666#define EVP_X_STATE(evp) (evp).cipher_data
667#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
668#endif
669
670int
671cipher_get_keycontext(CipherContext *cc, u_char *dat)
672{
673 Cipher *c = cc->cipher;
674 int plen;
675
676 if (c->number == SSH_CIPHER_3DES) {
677 struct ssh1_3des_ctx *desc;
678 desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
679 if (desc == NULL)
680 fatal("%s: no 3des context", __FUNCTION__);
681 plen = EVP_X_STATE_LEN(desc->k1);
682 if (dat == NULL)
683 return (3*plen);
684 memcpy(dat, EVP_X_STATE(desc->k1), plen);
685 memcpy(dat + plen, EVP_X_STATE(desc->k2), plen);
686 memcpy(dat + 2*plen, EVP_X_STATE(desc->k3), plen);
687 return (3*plen);
688 }
689
690 /* Generic EVP */
691 plen = EVP_X_STATE_LEN(cc->evp);
692 if (dat == NULL)
693 return (plen);
694
695 memcpy(dat, EVP_X_STATE(cc->evp), plen);
696 return (plen);
697}
698
699void
700cipher_set_keycontext(CipherContext *cc, u_char *dat)
701{
702 Cipher *c = cc->cipher;
703 int plen;
704
705 if (c->number == SSH_CIPHER_3DES) {
706 struct ssh1_3des_ctx *desc;
707 desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
708 if (desc == NULL)
709 fatal("%s: no 3des context", __FUNCTION__);
710 plen = EVP_X_STATE_LEN(desc->k1);
711 memcpy(EVP_X_STATE(desc->k1), dat, plen);
712 memcpy(EVP_X_STATE(desc->k2), dat + plen, plen);
713 memcpy(EVP_X_STATE(desc->k3), dat + 2*plen, plen);
714 } else {
715 plen = EVP_X_STATE_LEN(cc->evp);
716 memcpy(EVP_X_STATE(cc->evp), dat, plen);
717 }
70fc1609 718}
This page took 0.221477 seconds and 5 git commands to generate.