From a201bb3f8a55fed2e75a3d6cfcaf3721497c15f3 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 May 2003 13:41:23 +1000 Subject: - markus@cvs.openbsd.org 2003/04/12 10:13:57 [cipher.c] hide cipher details; ok djm@ --- cipher.c | 103 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 50 insertions(+), 53 deletions(-) (limited to 'cipher.c') diff --git a/cipher.c b/cipher.c index b5d38747e..b6637b645 100644 --- a/cipher.c +++ b/cipher.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.62 2002/11/21 22:45:31 markus Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.63 2003/04/12 10:13:57 markus Exp $"); #include "xmalloc.h" #include "log.h" @@ -395,6 +395,28 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) return (1); } +static void +ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) +{ + struct ssh1_3des_ctx *c; + + if (len != 24) + fatal("%s: bad 3des iv length: %d", __func__, len); + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal("%s: no 3des context", __func__); + if (doset) { + debug3("%s: Installed 3DES IV", __func__); + memcpy(c->k1.iv, iv, 8); + memcpy(c->k2.iv, iv + 8, 8); + memcpy(c->k3.iv, iv + 16, 8); + } else { + debug3("%s: Copying 3DES IV", __func__); + memcpy(iv, c->k1.iv, 8); + memcpy(iv + 8, c->k2.iv, 8); + memcpy(iv + 16, c->k3.iv, 8); + } +} + static const EVP_CIPHER * evp_ssh1_3des(void) { @@ -567,6 +589,19 @@ ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) return (1); } +static void +ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal("ssh_rijndael_iv: no context"); + if (doset) + memcpy(c->r_iv, iv, len); + else + memcpy(iv, c->r_iv, len); +} + static const EVP_CIPHER * evp_rijndael(void) { @@ -611,7 +646,6 @@ void cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) { Cipher *c = cc->cipher; - u_char *civ = NULL; int evplen; switch (c->number) { @@ -624,45 +658,25 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) if (evplen != len) fatal("%s: wrong iv length %d != %d", __func__, evplen, len); - #if OPENSSL_VERSION_NUMBER < 0x00907000L - if (c->evptype == evp_rijndael) { - struct ssh_rijndael_ctx *aesc; - - aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (aesc == NULL) - fatal("%s: no rijndael context", __func__); - civ = aesc->r_iv; - } else + if (c->evptype == evp_rijndael) + ssh_rijndael_iv(&cc->evp, 0, iv, len); + else #endif - { - civ = cc->evp.iv; - } + memcpy(iv, cc->evp.iv, len); + break; + case SSH_CIPHER_3DES: + ssh1_3des_iv(&cc->evp, 0, iv, 24); break; - case SSH_CIPHER_3DES: { - struct ssh1_3des_ctx *desc; - if (len != 24) - fatal("%s: bad 3des iv length: %d", __func__, len); - desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (desc == NULL) - fatal("%s: no 3des context", __func__); - debug3("%s: Copying 3DES IV", __func__); - memcpy(iv, desc->k1.iv, 8); - memcpy(iv + 8, desc->k2.iv, 8); - memcpy(iv + 16, desc->k3.iv, 8); - return; - } default: fatal("%s: bad cipher %d", __func__, c->number); } - memcpy(iv, civ, len); } void cipher_set_keyiv(CipherContext *cc, u_char *iv) { Cipher *c = cc->cipher; - u_char *div = NULL; int evplen = 0; switch (c->number) { @@ -672,36 +686,19 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv) evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); if (evplen == 0) return; - #if OPENSSL_VERSION_NUMBER < 0x00907000L - if (c->evptype == evp_rijndael) { - struct ssh_rijndael_ctx *aesc; - - aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (aesc == NULL) - fatal("%s: no rijndael context", __func__); - div = aesc->r_iv; - } else + if (c->evptype == evp_rijndael) + ssh_rijndael_iv(&cc->evp, 1, iv, evplen); + else #endif - { - div = cc->evp.iv; - } + memcpy(cc->evp.iv, iv, evplen); + break; + case SSH_CIPHER_3DES: + ssh1_3des_iv(&cc->evp, 1, iv, 24); break; - case SSH_CIPHER_3DES: { - struct ssh1_3des_ctx *desc; - desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); - if (desc == NULL) - fatal("%s: no 3des context", __func__); - debug3("%s: Installed 3DES IV", __func__); - memcpy(desc->k1.iv, iv, 8); - memcpy(desc->k2.iv, iv + 8, 8); - memcpy(desc->k3.iv, iv + 16, 8); - return; - } default: fatal("%s: bad cipher %d", __func__, c->number); } - memcpy(div, iv, evplen); } #if OPENSSL_VERSION_NUMBER < 0x00907000L -- cgit v1.2.3 From 3a3261ff99f660b8191f3e5366054566fb0a05de Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 15 May 2003 13:37:19 +1000 Subject: - markus@cvs.openbsd.org 2003/05/15 03:08:29 [cipher.c cipher-bf1.c cipher-aes.c cipher-3des1.c] split out custom EVP ciphers --- ChangeLog | 5 +- Makefile.in | 5 +- cipher-3des1.c | 171 +++++++++++++++++++++++++++++ cipher-aes.c | 156 ++++++++++++++++++++++++++ cipher-bf1.c | 97 +++++++++++++++++ cipher.c | 338 +-------------------------------------------------------- 6 files changed, 437 insertions(+), 335 deletions(-) create mode 100644 cipher-3des1.c create mode 100644 cipher-aes.c create mode 100644 cipher-bf1.c (limited to 'cipher.c') diff --git a/ChangeLog b/ChangeLog index 5243876e8..2e7aeb132 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,9 @@ - jakob@cvs.openbsd.org 2003/05/15 02:27:15 [dns.c] add missing freerrset + - markus@cvs.openbsd.org 2003/05/15 03:08:29 + [cipher.c cipher-bf1.c cipher-aes.c cipher-3des1.c] + split out custom EVP ciphers - (djm) Always parse UsePAM - (djm) Configure glue for DNS support (code doesn't work in portable yet) - (djm) Import getrrsetbyname() function from OpenBSD libc (for DNS support) @@ -1502,4 +1505,4 @@ save auth method before monitor_reset_key_state(); bugzilla bug #284; ok provos@ -$Id: ChangeLog,v 1.2710 2003/05/15 03:27:28 djm Exp $ +$Id: ChangeLog,v 1.2711 2003/05/15 03:37:19 djm Exp $ diff --git a/Makefile.in b/Makefile.in index 5758d0dbe..8bdef2031 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.234 2003/05/15 03:23:07 djm Exp $ +# $Id: Makefile.in,v 1.235 2003/05/15 03:37:20 djm Exp $ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -61,7 +61,8 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \ - cipher.o compat.o compress.o crc32.o deattack.o fatal.o \ + cipher.o cipher-aes.o cipher-bf1.o cipher-3des1.o \ + compat.o compress.o crc32.o deattack.o fatal.o \ hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o \ readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \ key.o dispatch.o kex.o mac.o uuencode.o misc.o \ diff --git a/cipher-3des1.c b/cipher-3des1.c new file mode 100644 index 000000000..f9a352397 --- /dev/null +++ b/cipher-3des1.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: cipher-3des1.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); + +#include +#include "xmalloc.h" +#include "log.h" + +/* + * This is used by SSH1: + * + * What kind of triple DES are these 2 routines? + * + * Why is there a redundant initialization vector? + * + * If only iv3 was used, then, this would till effect have been + * outer-cbc. However, there is also a private iv1 == iv2 which + * perhaps makes differential analysis easier. On the other hand, the + * private iv1 probably makes the CRC-32 attack ineffective. This is a + * result of that there is no longer any known iv1 to use when + * choosing the X block. + */ +struct ssh1_3des_ctx +{ + EVP_CIPHER_CTX k1, k2, k3; +}; + +const EVP_CIPHER * evp_ssh1_3des(void); +void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); + +static int +ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh1_3des_ctx *c; + u_char *k1, *k2, *k3; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key == NULL) + return (1); + if (enc == -1) + enc = ctx->encrypt; + k1 = k2 = k3 = (u_char *) key; + k2 += 8; + if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { + if (enc) + k3 += 16; + else + k1 += 16; + } + EVP_CIPHER_CTX_init(&c->k1); + EVP_CIPHER_CTX_init(&c->k2); + EVP_CIPHER_CTX_init(&c->k3); +#ifdef SSH_OLD_EVP + EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); + EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); + EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); +#else + if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || + EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || + EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + return (0); + } +#endif + return (1); +} + +static int +ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len) +{ + struct ssh1_3des_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + error("ssh1_3des_cbc: no context"); + return (0); + } +#ifdef SSH_OLD_EVP + EVP_Cipher(&c->k1, dest, (u_char *)src, len); + EVP_Cipher(&c->k2, dest, dest, len); + EVP_Cipher(&c->k3, dest, dest, len); +#else + if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || + EVP_Cipher(&c->k2, dest, dest, len) == 0 || + EVP_Cipher(&c->k3, dest, dest, len) == 0) + return (0); +#endif + return (1); +} + +static int +ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh1_3des_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +void +ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) +{ + struct ssh1_3des_ctx *c; + + if (len != 24) + fatal("%s: bad 3des iv length: %d", __func__, len); + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal("%s: no 3des context", __func__); + if (doset) { + debug3("%s: Installed 3DES IV", __func__); + memcpy(c->k1.iv, iv, 8); + memcpy(c->k2.iv, iv + 8, 8); + memcpy(c->k3.iv, iv + 16, 8); + } else { + debug3("%s: Copying 3DES IV", __func__); + memcpy(iv, c->k1.iv, 8); + memcpy(iv + 8, c->k2.iv, 8); + memcpy(iv + 16, c->k3.iv, 8); + } +} + +const EVP_CIPHER * +evp_ssh1_3des(void) +{ + static EVP_CIPHER ssh1_3des; + + memset(&ssh1_3des, 0, sizeof(EVP_CIPHER)); + ssh1_3des.nid = NID_undef; + ssh1_3des.block_size = 8; + ssh1_3des.iv_len = 0; + ssh1_3des.key_len = 16; + ssh1_3des.init = ssh1_3des_init; + ssh1_3des.cleanup = ssh1_3des_cleanup; + ssh1_3des.do_cipher = ssh1_3des_cbc; +#ifndef SSH_OLD_EVP + ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; +#endif + return (&ssh1_3des); +} diff --git a/cipher-aes.c b/cipher-aes.c new file mode 100644 index 000000000..bbfbe7210 --- /dev/null +++ b/cipher-aes.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2003 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +#include "includes.h" +RCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); + +#include +#include "rijndael.h" +#include "xmalloc.h" +#include "log.h" + +#define RIJNDAEL_BLOCKSIZE 16 +struct ssh_rijndael_ctx +{ + rijndael_ctx r_ctx; + u_char r_iv[RIJNDAEL_BLOCKSIZE]; +}; + +const EVP_CIPHER * evp_rijndael(void); +void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); + +static int +ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key != NULL) { + if (enc == -1) + enc = ctx->encrypt; + rijndael_set_key(&c->r_ctx, (u_char *)key, + 8*EVP_CIPHER_CTX_key_length(ctx), enc); + } + if (iv != NULL) + memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); + return (1); +} + +static int +ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, + u_int len) +{ + struct ssh_rijndael_ctx *c; + u_char buf[RIJNDAEL_BLOCKSIZE]; + u_char *cprev, *cnow, *plain, *ivp; + int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; + + if (len == 0) + return (1); + if (len % RIJNDAEL_BLOCKSIZE) + fatal("ssh_rijndael_cbc: bad len %d", len); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + error("ssh_rijndael_cbc: no context"); + return (0); + } + if (ctx->encrypt) { + cnow = dest; + plain = (u_char *)src; + cprev = c->r_iv; + for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, + cnow+=RIJNDAEL_BLOCKSIZE) { + for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) + buf[j] = plain[j] ^ cprev[j]; + rijndael_encrypt(&c->r_ctx, buf, cnow); + cprev = cnow; + } + memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); + } else { + cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); + plain = dest+len-RIJNDAEL_BLOCKSIZE; + + memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); + for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, + plain-=RIJNDAEL_BLOCKSIZE) { + rijndael_decrypt(&c->r_ctx, cnow, plain); + ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; + for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) + plain[j] ^= ivp[j]; + } + memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); + } + return (1); +} + +static int +ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +void +ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal("ssh_rijndael_iv: no context"); + if (doset) + memcpy(c->r_iv, iv, len); + else + memcpy(iv, c->r_iv, len); +} + +const EVP_CIPHER * +evp_rijndael(void) +{ + static EVP_CIPHER rijndal_cbc; + + memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); + rijndal_cbc.nid = NID_undef; + rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; + rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; + rijndal_cbc.key_len = 16; + rijndal_cbc.init = ssh_rijndael_init; + rijndal_cbc.cleanup = ssh_rijndael_cleanup; + rijndal_cbc.do_cipher = ssh_rijndael_cbc; +#ifndef SSH_OLD_EVP + rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; +#endif + return (&rijndal_cbc); +} +#endif diff --git a/cipher-bf1.c b/cipher-bf1.c new file mode 100644 index 000000000..64578bae8 --- /dev/null +++ b/cipher-bf1.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: cipher-bf1.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); + +#include +#include "xmalloc.h" +#include "log.h" +/* + * SSH1 uses a variation on Blowfish, all bytes must be swapped before + * and after encryption/decryption. Thus the swap_bytes stuff (yuk). + */ + +const EVP_CIPHER * evp_ssh1_bf(void); + +static void +swap_bytes(const u_char *src, u_char *dst, int n) +{ + u_char c[4]; + + /* Process 4 bytes every lap. */ + for (n = n / 4; n > 0; n--) { + c[3] = *src++; + c[2] = *src++; + c[1] = *src++; + c[0] = *src++; + + *dst++ = c[0]; + *dst++ = c[1]; + *dst++ = c[2]; + *dst++ = c[3]; + } +} + +#ifdef SSH_OLD_EVP +static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + if (iv != NULL) + memcpy (&(ctx->oiv[0]), iv, 8); + memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8); + if (key != NULL) + BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx), + key); +} +#endif + +static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL; + +static int +bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len) +{ + int ret; + + swap_bytes(in, out, len); + ret = (*orig_bf)(ctx, out, out, len); + swap_bytes(out, out, len); + return (ret); +} + +const EVP_CIPHER * +evp_ssh1_bf(void) +{ + static EVP_CIPHER ssh1_bf; + + memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); + orig_bf = ssh1_bf.do_cipher; + ssh1_bf.nid = NID_undef; +#ifdef SSH_OLD_EVP + ssh1_bf.init = bf_ssh1_init; +#endif + ssh1_bf.do_cipher = bf_ssh1_cipher; + ssh1_bf.key_len = 32; + return (&ssh1_bf); +} diff --git a/cipher.c b/cipher.c index b6637b645..acb436c8a 100644 --- a/cipher.c +++ b/cipher.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.63 2003/04/12 10:13:57 markus Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.64 2003/05/15 03:08:29 markus Exp $"); #include "xmalloc.h" #include "log.h" @@ -49,11 +49,12 @@ RCSID("$OpenBSD: cipher.c,v 1.63 2003/04/12 10:13:57 markus Exp $"); #endif #if OPENSSL_VERSION_NUMBER < 0x00907000L -#include "rijndael.h" -static const EVP_CIPHER *evp_rijndael(void); +extern const EVP_CIPHER *evp_rijndael(void); +extern void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); #endif -static const EVP_CIPHER *evp_ssh1_3des(void); -static const EVP_CIPHER *evp_ssh1_bf(void); +extern const EVP_CIPHER *evp_ssh1_bf(void); +extern const EVP_CIPHER *evp_ssh1_3des(void); +extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); struct Cipher { char *name; @@ -296,333 +297,6 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher, memset(&md, 0, sizeof(md)); } -/* Implementations for other non-EVP ciphers */ - -/* - * This is used by SSH1: - * - * What kind of triple DES are these 2 routines? - * - * Why is there a redundant initialization vector? - * - * If only iv3 was used, then, this would till effect have been - * outer-cbc. However, there is also a private iv1 == iv2 which - * perhaps makes differential analysis easier. On the other hand, the - * private iv1 probably makes the CRC-32 attack ineffective. This is a - * result of that there is no longer any known iv1 to use when - * choosing the X block. - */ -struct ssh1_3des_ctx -{ - EVP_CIPHER_CTX k1, k2, k3; -}; - -static int -ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, - int enc) -{ - struct ssh1_3des_ctx *c; - u_char *k1, *k2, *k3; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } - if (key == NULL) - return (1); - if (enc == -1) - enc = ctx->encrypt; - k1 = k2 = k3 = (u_char *) key; - k2 += 8; - if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { - if (enc) - k3 += 16; - else - k1 += 16; - } - EVP_CIPHER_CTX_init(&c->k1); - EVP_CIPHER_CTX_init(&c->k2); - EVP_CIPHER_CTX_init(&c->k3); -#ifdef SSH_OLD_EVP - EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); - EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); - EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); -#else - if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || - EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || - EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - return (0); - } -#endif - return (1); -} - -static int -ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - error("ssh1_3des_cbc: no context"); - return (0); - } -#ifdef SSH_OLD_EVP - EVP_Cipher(&c->k1, dest, (u_char *)src, len); - EVP_Cipher(&c->k2, dest, dest, len); - EVP_Cipher(&c->k3, dest, dest, len); -#else - if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || - EVP_Cipher(&c->k2, dest, dest, len) == 0 || - EVP_Cipher(&c->k3, dest, dest, len) == 0) - return (0); -#endif - return (1); -} - -static int -ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - } - return (1); -} - -static void -ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) -{ - struct ssh1_3des_ctx *c; - - if (len != 24) - fatal("%s: bad 3des iv length: %d", __func__, len); - if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - fatal("%s: no 3des context", __func__); - if (doset) { - debug3("%s: Installed 3DES IV", __func__); - memcpy(c->k1.iv, iv, 8); - memcpy(c->k2.iv, iv + 8, 8); - memcpy(c->k3.iv, iv + 16, 8); - } else { - debug3("%s: Copying 3DES IV", __func__); - memcpy(iv, c->k1.iv, 8); - memcpy(iv + 8, c->k2.iv, 8); - memcpy(iv + 16, c->k3.iv, 8); - } -} - -static const EVP_CIPHER * -evp_ssh1_3des(void) -{ - static EVP_CIPHER ssh1_3des; - - memset(&ssh1_3des, 0, sizeof(EVP_CIPHER)); - ssh1_3des.nid = NID_undef; - ssh1_3des.block_size = 8; - ssh1_3des.iv_len = 0; - ssh1_3des.key_len = 16; - ssh1_3des.init = ssh1_3des_init; - ssh1_3des.cleanup = ssh1_3des_cleanup; - ssh1_3des.do_cipher = ssh1_3des_cbc; -#ifndef SSH_OLD_EVP - ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; -#endif - return (&ssh1_3des); -} - -/* - * SSH1 uses a variation on Blowfish, all bytes must be swapped before - * and after encryption/decryption. Thus the swap_bytes stuff (yuk). - */ -static void -swap_bytes(const u_char *src, u_char *dst, int n) -{ - u_char c[4]; - - /* Process 4 bytes every lap. */ - for (n = n / 4; n > 0; n--) { - c[3] = *src++; - c[2] = *src++; - c[1] = *src++; - c[0] = *src++; - - *dst++ = c[0]; - *dst++ = c[1]; - *dst++ = c[2]; - *dst++ = c[3]; - } -} - -#ifdef SSH_OLD_EVP -static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key, - const unsigned char *iv, int enc) -{ - if (iv != NULL) - memcpy (&(ctx->oiv[0]), iv, 8); - memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8); - if (key != NULL) - BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx), - key); -} -#endif -static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL; - -static int -bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len) -{ - int ret; - - swap_bytes(in, out, len); - ret = (*orig_bf)(ctx, out, out, len); - swap_bytes(out, out, len); - return (ret); -} - -static const EVP_CIPHER * -evp_ssh1_bf(void) -{ - static EVP_CIPHER ssh1_bf; - - memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); - orig_bf = ssh1_bf.do_cipher; - ssh1_bf.nid = NID_undef; -#ifdef SSH_OLD_EVP - ssh1_bf.init = bf_ssh1_init; -#endif - ssh1_bf.do_cipher = bf_ssh1_cipher; - ssh1_bf.key_len = 32; - return (&ssh1_bf); -} - -#if OPENSSL_VERSION_NUMBER < 0x00907000L -/* RIJNDAEL */ -#define RIJNDAEL_BLOCKSIZE 16 -struct ssh_rijndael_ctx -{ - rijndael_ctx r_ctx; - u_char r_iv[RIJNDAEL_BLOCKSIZE]; -}; - -static int -ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, - int enc) -{ - struct ssh_rijndael_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } - if (key != NULL) { - if (enc == -1) - enc = ctx->encrypt; - rijndael_set_key(&c->r_ctx, (u_char *)key, - 8*EVP_CIPHER_CTX_key_length(ctx), enc); - } - if (iv != NULL) - memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); - return (1); -} - -static int -ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, - u_int len) -{ - struct ssh_rijndael_ctx *c; - u_char buf[RIJNDAEL_BLOCKSIZE]; - u_char *cprev, *cnow, *plain, *ivp; - int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; - - if (len == 0) - return (1); - if (len % RIJNDAEL_BLOCKSIZE) - fatal("ssh_rijndael_cbc: bad len %d", len); - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - error("ssh_rijndael_cbc: no context"); - return (0); - } - if (ctx->encrypt) { - cnow = dest; - plain = (u_char *)src; - cprev = c->r_iv; - for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, - cnow+=RIJNDAEL_BLOCKSIZE) { - for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) - buf[j] = plain[j] ^ cprev[j]; - rijndael_encrypt(&c->r_ctx, buf, cnow); - cprev = cnow; - } - memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); - } else { - cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); - plain = dest+len-RIJNDAEL_BLOCKSIZE; - - memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); - for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, - plain-=RIJNDAEL_BLOCKSIZE) { - rijndael_decrypt(&c->r_ctx, cnow, plain); - ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; - for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) - plain[j] ^= ivp[j]; - } - memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); - } - return (1); -} - -static int -ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) -{ - struct ssh_rijndael_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - } - return (1); -} - -static void -ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) -{ - struct ssh_rijndael_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - fatal("ssh_rijndael_iv: no context"); - if (doset) - memcpy(c->r_iv, iv, len); - else - memcpy(iv, c->r_iv, len); -} - -static const EVP_CIPHER * -evp_rijndael(void) -{ - static EVP_CIPHER rijndal_cbc; - - memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); - rijndal_cbc.nid = NID_undef; - rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; - rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; - rijndal_cbc.key_len = 16; - rijndal_cbc.init = ssh_rijndael_init; - rijndal_cbc.cleanup = ssh_rijndael_cleanup; - rijndal_cbc.do_cipher = ssh_rijndael_cbc; -#ifndef SSH_OLD_EVP - rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | - EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -#endif - return (&rijndal_cbc); -} -#endif - /* * Exports an IV from the CipherContext required to export the key * state back from the unprivileged child to the privileged parent -- cgit v1.2.3 From f5399c24dc53a9afebf089a013a0359e7c775a90 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 18 May 2003 20:53:59 +1000 Subject: - markus@cvs.openbsd.org 2003/05/17 04:27:52 [cipher.c cipher-ctr.c myproposal.h] experimental support for aes-ctr modes from http://www.ietf.org/internet-drafts/draft-ietf-secsh-newmodes-00.txt ok djm@ --- ChangeLog | 7 ++- Makefile.in | 4 +- cipher-ctr.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cipher.c | 13 +++++- myproposal.h | 5 +- 5 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 cipher-ctr.c (limited to 'cipher.c') diff --git a/ChangeLog b/ChangeLog index 0e5bb37e2..ee0099624 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,11 @@ - itojun@cvs.openbsd.org 2003/05/17 03:25:58 [auth-rhosts.c] just in case, put numbers to sscanf %s arg. + - markus@cvs.openbsd.org 2003/05/17 04:27:52 + [cipher.c cipher-ctr.c myproposal.h] + experimental support for aes-ctr modes from + http://www.ietf.org/internet-drafts/draft-ietf-secsh-newmodes-00.txt + ok djm@ - (djm) Remove IPv4 by default hack now that we can specify AF in config 20030517 @@ -1565,4 +1570,4 @@ save auth method before monitor_reset_key_state(); bugzilla bug #284; ok provos@ -$Id: ChangeLog,v 1.2735 2003/05/18 10:53:10 djm Exp $ +$Id: ChangeLog,v 1.2736 2003/05/18 10:53:59 djm Exp $ diff --git a/Makefile.in b/Makefile.in index 004f05466..33058a828 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.236 2003/05/15 11:33:46 djm Exp $ +# $Id: Makefile.in,v 1.237 2003/05/18 10:53:59 djm Exp $ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -61,7 +61,7 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \ - cipher.o cipher-aes.o cipher-bf1.o cipher-3des1.o \ + cipher.o cipher-aes.o cipher-bf1.o cipher-ctr.o cipher-3des1.o \ compat.o compress.o crc32.o deattack.o fatal.o \ hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o \ readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \ diff --git a/cipher-ctr.c b/cipher-ctr.c new file mode 100644 index 000000000..8d548c708 --- /dev/null +++ b/cipher-ctr.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2003 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "includes.h" +RCSID("$OpenBSD: cipher-ctr.c,v 1.1 2003/05/17 04:27:52 markus Exp $"); + +#include + +#include "log.h" +#include "xmalloc.h" + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +#include "rijndael.h" +#define AES_KEY rijndael_ctx +#define AES_BLOCK_SIZE 16 +#define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b) +#define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1) +#else +#include +#endif + +const EVP_CIPHER *evp_aes_128_ctr(void); +void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); + +struct ssh_aes_ctr_ctx +{ + AES_KEY aes_ctx; + u_char aes_counter[AES_BLOCK_SIZE]; +}; + +/* + * increment counter 'ctr', + * the counter is of size 'len' bytes and stored in network-byte-order. + * (LSB at ctr[len-1], MSB at ctr[0]) + */ +static void +ssh_ctr_inc(u_char *ctr, u_int len) +{ + int i; + + for (i = len - 1; i >= 0; i--) + if (++ctr[i]) /* continue on overflow */ + return; +} + +static int +ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, + u_int len) +{ + struct ssh_aes_ctr_ctx *c; + u_int n = 0; + u_char buf[AES_BLOCK_SIZE]; + + if (len == 0) + return (1); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) + return (0); + + while ((len--) > 0) { + if (n == 0) { + AES_encrypt(c->aes_counter, buf, &c->aes_ctx); + ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); + } + *(dest++) = *(src++) ^ buf[n]; + n = (n + 1) % AES_BLOCK_SIZE; + } + return (1); +} + +static int +ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key != NULL) + AES_set_encrypt_key(key, ctx->key_len * 8, &c->aes_ctx); + if (iv != NULL) + memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); + return (1); +} + +static int +ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +void +ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) +{ + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal("ssh_aes_ctr_iv: no context"); + if (doset) + memcpy(c->aes_counter, iv, len); + else + memcpy(iv, c->aes_counter, len); +} + +const EVP_CIPHER * +evp_aes_128_ctr(void) +{ + static EVP_CIPHER aes_ctr; + + memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); + aes_ctr.nid = NID_undef; + aes_ctr.block_size = AES_BLOCK_SIZE; + aes_ctr.iv_len = AES_BLOCK_SIZE; + aes_ctr.key_len = 16; + aes_ctr.init = ssh_aes_ctr_init; + aes_ctr.cleanup = ssh_aes_ctr_cleanup; + aes_ctr.do_cipher = ssh_aes_ctr; + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; + return (&aes_ctr); +} diff --git a/cipher.c b/cipher.c index acb436c8a..e7c3c5411 100644 --- a/cipher.c +++ b/cipher.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.64 2003/05/15 03:08:29 markus Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.65 2003/05/17 04:27:52 markus Exp $"); #include "xmalloc.h" #include "log.h" @@ -55,6 +55,8 @@ extern void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); extern const EVP_CIPHER *evp_ssh1_bf(void); extern const EVP_CIPHER *evp_ssh1_3des(void); extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); +extern const EVP_CIPHER *evp_aes_128_ctr(void); +extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); struct Cipher { char *name; @@ -85,6 +87,9 @@ struct Cipher { { "rijndael-cbc@lysator.liu.se", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, #endif + { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, + { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, + { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } }; @@ -337,6 +342,9 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) ssh_rijndael_iv(&cc->evp, 0, iv, len); else #endif + if (c->evptype == evp_aes_128_ctr) + ssh_aes_ctr_iv(&cc->evp, 0, iv, len); + else memcpy(iv, cc->evp.iv, len); break; case SSH_CIPHER_3DES: @@ -365,6 +373,9 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv) ssh_rijndael_iv(&cc->evp, 1, iv, evplen); else #endif + if (c->evptype == evp_aes_128_ctr) + ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen); + else memcpy(cc->evp.iv, iv, evplen); break; case SSH_CIPHER_3DES: diff --git a/myproposal.h b/myproposal.h index 62f5cfb65..8b431d9d2 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */ +/* $OpenBSD: myproposal.h,v 1.15 2003/05/17 04:27:52 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -27,7 +27,8 @@ #define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" #define KEX_DEFAULT_ENCRYPT \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ - "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" + "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ + "aes128-ctr,aes192-ctr,aes256-ctr" #define KEX_DEFAULT_MAC \ "hmac-md5,hmac-sha1,hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ -- cgit v1.2.3 From e043e8e2211ee07e98f95fe975cca56959eb6c59 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 23 Sep 2003 19:24:21 +1000 Subject: - (djm) Fix SSH1 challenge kludge - (djm) Bug #671: Fix builds on OpenBSD - (djm) Bug #676: Fix PAM stack corruption - (djm) Fix bad free() in PAM code - (djm) Don't call pam_end before pam_init - (djm) Enable build with old OpenSSL again - (djm) Trim deprecated options from INSTALL. Mention UsePAM - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu --- ChangeLog | 10 ++++++- INSTALL | 19 +++---------- auth-chall.c | 2 +- auth-pam.c | 84 +++++++++++++++++++++++++++++++++++++--------------------- cipher-3des1.c | 4 +++ cipher-aes.c | 4 +++ cipher-bf1.c | 5 ++++ cipher-ctr.c | 6 +++++ cipher.c | 2 ++ configure.ac | 4 +-- log.c | 3 +++ servconf.c | 2 +- sftp-int.c | 1 + 13 files changed, 95 insertions(+), 51 deletions(-) (limited to 'cipher.c') diff --git a/ChangeLog b/ChangeLog index b49a8536e..9b34d4a6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,14 @@ - markus@cvs.openbsd.org 2003/09/19 09:02:02 [packet.c] buffer_dump only if PACKET_DEBUG is defined; Jedi/Sector One; pr 3471 + - (djm) Fix SSH1 challenge kludge + - (djm) Bug #671: Fix builds on OpenBSD + - (djm) Bug #676: Fix PAM stack corruption + - (djm) Fix bad free() in PAM code + - (djm) Don't call pam_end before pam_init + - (djm) Enable build with old OpenSSL again + - (djm) Trim deprecated options from INSTALL. Mention UsePAM + - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 20030922 - (dtucker) [Makefile.in] Bug #644: Fix "make clean" for out-of-tree @@ -1178,4 +1186,4 @@ - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. Report from murple@murple.net, diagnosis from dtucker@zip.com.au -$Id: ChangeLog,v 1.2994.2.31 2003/09/23 09:00:41 dtucker Exp $ +$Id: ChangeLog,v 1.2994.2.32 2003/09/23 09:24:21 djm Exp $ diff --git a/INSTALL b/INSTALL index 7b6f71d53..0df6fba10 100644 --- a/INSTALL +++ b/INSTALL @@ -101,11 +101,8 @@ name). There are a few other options to the configure script: ---with-pam enables PAM support. - ---enable-gnome-askpass will build the GNOME passphrase dialog. You -need a working installation of GNOME, including the development -headers, for this to work. +--with-pam enables PAM support. If PAM support is compiled in, it must +also be enabled in sshd_config (refer to the UsePAM directive). --with-prngd-socket=/some/file allows you to enable EGD or PRNGD support and to specify a PRNGd socket. Use this if your Unix lacks @@ -126,16 +123,6 @@ it if lastlog is installed in a different place. --with-osfsia, --without-osfsia will enable or disable OSF1's Security Integration Architecture. The default for OSF1 machines is enable. ---with-kerberos4=PATH will enable Kerberos IV support. You will need -to have the Kerberos libraries and header files installed for this -to work. Use the optional PATH argument to specify the root of your -Kerberos installation. - ---with-afs=PATH will enable AFS support. You will need to have the -Kerberos IV and the AFS libraries and header files installed for this -to work. Use the optional PATH argument to specify the root of your -AFS installation. AFS requires Kerberos support to be enabled. - --with-skey=PATH will enable S/Key one time password support. You will need the S/Key libraries and header files installed for this to work. @@ -211,4 +198,4 @@ Please refer to the "reporting bugs" section of the webpage at http://www.openssh.com/ -$Id: INSTALL,v 1.56.2.3 2003/09/22 03:29:00 dtucker Exp $ +$Id: INSTALL,v 1.56.2.4 2003/09/23 09:24:21 djm Exp $ diff --git a/auth-chall.c b/auth-chall.c index 6b7c8bd13..00d6e0ec5 100644 --- a/auth-chall.c +++ b/auth-chall.c @@ -92,7 +92,7 @@ verify_response(Authctxt *authctxt, const char *response) xfree(info); } /* if we received more prompts, we're screwed */ - res = (numprompts != 0); + res = (res == 0 && numprompts == 0) ? 0 : -1; } device->free_ctx(authctxt->kbdintctxt); authctxt->kbdintctxt = NULL; diff --git a/auth-pam.c b/auth-pam.c index 754cbf6df..2c8feb65d 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -31,7 +31,7 @@ /* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ #include "includes.h" -RCSID("$Id: auth-pam.c,v 1.72.2.1 2003/09/16 06:00:52 djm Exp $"); +RCSID("$Id: auth-pam.c,v 1.72.2.2 2003/09/23 09:24:21 djm Exp $"); #ifdef USE_PAM #include @@ -111,12 +111,12 @@ pthread_join(sp_pthread_t thread, void **value __unused) #endif -static pam_handle_t *sshpam_handle; -static int sshpam_err; -static int sshpam_authenticated; -static int sshpam_new_authtok_reqd; -static int sshpam_session_open; -static int sshpam_cred_established; +static pam_handle_t *sshpam_handle = NULL; +static int sshpam_err = 0; +static int sshpam_authenticated = 0; +static int sshpam_new_authtok_reqd = 0; +static int sshpam_session_open = 0; +static int sshpam_cred_established = 0; struct pam_ctxt { sp_pthread_t pam_thread; @@ -136,42 +136,51 @@ sshpam_thread_conv(int n, const struct pam_message **msg, { Buffer buffer; struct pam_ctxt *ctxt; + struct pam_response *reply; int i; + *resp = NULL; + ctxt = data; if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); - *resp = xmalloc(n * sizeof **resp); + + if ((reply = malloc(n * sizeof(*reply))) == NULL) + return (PAM_CONV_ERR); + memset(reply, 0, n * sizeof(*reply)); + buffer_init(&buffer); for (i = 0; i < n; ++i) { - resp[i]->resp_retcode = 0; - resp[i]->resp = NULL; switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_PROMPT_ECHO_OFF: - buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg)); + buffer_put_cstring(&buffer, + PAM_MSG_MEMBER(msg, i, msg)); ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), &buffer); ssh_msg_recv(ctxt->pam_csock, &buffer); if (buffer_get_char(&buffer) != PAM_AUTHTOK) goto fail; - resp[i]->resp = buffer_get_string(&buffer, NULL); + reply[i].resp = buffer_get_string(&buffer, NULL); break; case PAM_PROMPT_ECHO_ON: - buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg)); + buffer_put_cstring(&buffer, + PAM_MSG_MEMBER(msg, i, msg)); ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), &buffer); ssh_msg_recv(ctxt->pam_csock, &buffer); if (buffer_get_char(&buffer) != PAM_AUTHTOK) goto fail; - resp[i]->resp = buffer_get_string(&buffer, NULL); + reply[i].resp = buffer_get_string(&buffer, NULL); break; case PAM_ERROR_MSG: - buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg)); + buffer_put_cstring(&buffer, + PAM_MSG_MEMBER(msg, i, msg)); ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), &buffer); break; case PAM_TEXT_INFO: - buffer_put_cstring(&buffer, PAM_MSG_MEMBER(msg, i, msg)); + buffer_put_cstring(&buffer, + PAM_MSG_MEMBER(msg, i, msg)); ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), &buffer); break; @@ -181,12 +190,15 @@ sshpam_thread_conv(int n, const struct pam_message **msg, buffer_clear(&buffer); } buffer_free(&buffer); + *resp = reply; return (PAM_SUCCESS); + fail: - while (i) - xfree(resp[--i]); - xfree(*resp); - *resp = NULL; + for(i = 0; i < n; i++) { + if (reply[i].resp != NULL) + xfree(reply[i].resp); + } + xfree(reply); buffer_free(&buffer); return (PAM_CONV_ERR); } @@ -258,6 +270,8 @@ sshpam_cleanup(void *arg) { (void)arg; debug("PAM: cleanup"); + if (sshpam_handle == NULL) + return; pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); if (sshpam_cred_established) { pam_setcred(sshpam_handle, PAM_DELETE_CRED); @@ -600,40 +614,50 @@ pam_chauthtok_conv(int n, const struct pam_message **msg, struct pam_response **resp, void *data) { char input[PAM_MAX_MSG_SIZE]; + struct pam_response *reply; int i; + *resp = NULL; + if (n <= 0 || n > PAM_MAX_NUM_MSG) return (PAM_CONV_ERR); - *resp = xmalloc(n * sizeof **resp); + + if ((reply = malloc(n * sizeof(*reply))) == NULL) + return (PAM_CONV_ERR); + memset(reply, 0, n * sizeof(*reply)); + for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { case PAM_PROMPT_ECHO_OFF: - resp[i]->resp = + reply[i].resp = read_passphrase(PAM_MSG_MEMBER(msg, i, msg), RP_ALLOW_STDIN); - resp[i]->resp_retcode = PAM_SUCCESS; + reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_PROMPT_ECHO_ON: fputs(PAM_MSG_MEMBER(msg, i, msg), stderr); fgets(input, sizeof input, stdin); - resp[i]->resp = xstrdup(input); - resp[i]->resp_retcode = PAM_SUCCESS; + reply[i].resp = xstrdup(input); + reply[i].resp_retcode = PAM_SUCCESS; break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: fputs(PAM_MSG_MEMBER(msg, i, msg), stderr); - resp[i]->resp_retcode = PAM_SUCCESS; + reply[i].resp_retcode = PAM_SUCCESS; break; default: goto fail; } } + *resp = reply; return (PAM_SUCCESS); + fail: - while (i) - xfree(resp[--i]); - xfree(*resp); - *resp = NULL; + for(i = 0; i < n; i++) { + if (reply[i].resp != NULL) + xfree(reply[i].resp); + } + xfree(reply); return (PAM_CONV_ERR); } diff --git a/cipher-3des1.c b/cipher-3des1.c index f9a352397..6f9f5dd6b 100644 --- a/cipher-3des1.c +++ b/cipher-3des1.c @@ -29,6 +29,10 @@ RCSID("$OpenBSD: cipher-3des1.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); #include "xmalloc.h" #include "log.h" +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#endif + /* * This is used by SSH1: * diff --git a/cipher-aes.c b/cipher-aes.c index c41def600..7ba950191 100644 --- a/cipher-aes.c +++ b/cipher-aes.c @@ -31,6 +31,10 @@ RCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); #include "xmalloc.h" #include "log.h" +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#endif + #define RIJNDAEL_BLOCKSIZE 16 struct ssh_rijndael_ctx { diff --git a/cipher-bf1.c b/cipher-bf1.c index 64578bae8..5af695c17 100644 --- a/cipher-bf1.c +++ b/cipher-bf1.c @@ -28,6 +28,11 @@ RCSID("$OpenBSD: cipher-bf1.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); #include #include "xmalloc.h" #include "log.h" + +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#endif + /* * SSH1 uses a variation on Blowfish, all bytes must be swapped before * and after encryption/decryption. Thus the swap_bytes stuff (yuk). diff --git a/cipher-ctr.c b/cipher-ctr.c index a2bab5c14..4f0814b22 100644 --- a/cipher-ctr.c +++ b/cipher-ctr.c @@ -21,6 +21,10 @@ RCSID("$OpenBSD: cipher-ctr.c,v 1.2 2003/06/17 18:14:23 markus Exp $"); #include "log.h" #include "xmalloc.h" +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#endif + #if OPENSSL_VERSION_NUMBER < 0x00907000L #include "rijndael.h" #define AES_KEY rijndael_ctx @@ -135,7 +139,9 @@ evp_aes_128_ctr(void) aes_ctr.init = ssh_aes_ctr_init; aes_ctr.cleanup = ssh_aes_ctr_cleanup; aes_ctr.do_cipher = ssh_aes_ctr; +#ifndef SSH_OLD_EVP aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; +#endif return (&aes_ctr); } diff --git a/cipher.c b/cipher.c index e7c3c5411..ce533670b 100644 --- a/cipher.c +++ b/cipher.c @@ -87,9 +87,11 @@ struct Cipher { { "rijndael-cbc@lysator.liu.se", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, #endif +#if OPENSSL_VERSION_NUMBER >= 0x00906000L { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, +#endif { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } }; diff --git a/configure.ac b/configure.ac index 716431080..916dc1075 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.154.2.10 2003/09/23 02:51:37 tim Exp $ +# $Id: configure.ac,v 1.154.2.11 2003/09/23 09:24:21 djm Exp $ AC_INIT AC_CONFIG_SRCDIR([ssh.c]) @@ -480,7 +480,7 @@ AC_CHECK_HEADERS(bstring.h crypt.h endian.h features.h floatingpoint.h \ sys/cdefs.h sys/mman.h sys/pstat.h sys/select.h sys/stat.h \ sys/stropts.h sys/sysmacros.h sys/time.h sys/timers.h \ sys/un.h time.h tmpdir.h ttyent.h usersec.h \ - util.h utime.h utmp.h utmpx.h) + util.h utime.h utmp.h utmpx.h vis.h) # Checks for libraries. AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match)) diff --git a/log.c b/log.c index 58ce8e5dd..9bce2555b 100644 --- a/log.c +++ b/log.c @@ -40,6 +40,9 @@ RCSID("$OpenBSD: log.c,v 1.28 2003/05/24 09:02:22 djm Exp $"); #include "xmalloc.h" #include +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) +# include +#endif static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; diff --git a/servconf.c b/servconf.c index 71e28b3cb..58f49a2f4 100644 --- a/servconf.c +++ b/servconf.c @@ -110,7 +110,7 @@ fill_default_server_options(ServerOptions *options) { /* Portable-specific options */ if (options->use_pam == -1) - options->use_pam = 1; + options->use_pam = 0; /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) diff --git a/sftp-int.c b/sftp-int.c index 94299aa43..c93eaabff 100644 --- a/sftp-int.c +++ b/sftp-int.c @@ -351,6 +351,7 @@ get_pathname(const char **cpp, char **path) for (i = j = 0; i <= strlen(cp); i++) { if (cp[i] == quot) { /* Found quote */ (*path)[j] = '\0'; + i++; break; } if (cp[i] == '\0') { /* End of string */ -- cgit v1.2.3