mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-12-26 11:52:06 +00:00
- 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
This commit is contained in:
parent
b0622653ba
commit
3a3261ff99
@ -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 $
|
||||
|
@ -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 \
|
||||
|
171
cipher-3des1.c
Normal file
171
cipher-3des1.c
Normal file
@ -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 <openssl/evp.h>
|
||||
#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);
|
||||
}
|
156
cipher-aes.c
Normal file
156
cipher-aes.c
Normal file
@ -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 <openssl/evp.h>
|
||||
#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
|
97
cipher-bf1.c
Normal file
97
cipher-bf1.c
Normal file
@ -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 <openssl/evp.h>
|
||||
#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);
|
||||
}
|
338
cipher.c
338
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
|
||||
|
Loading…
Reference in New Issue
Block a user