source: trunk/third/openssh/cipher.c @ 18759

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