summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2002-02-14 23:41:02 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2002-02-14 23:41:02 +0000
commit66749939441629fabaae01d2514da1fb4c3b2111 (patch)
tree92a116ebf19f520820da906b492f097bd5d2be30 /usr.bin/ssh
parent421b9dda786af8fb41ec7746c67f5be9b374b083 (diff)
hide some more implementation details of cipher.[ch] and prepares for move
to EVP, ok deraadt@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/authfile.c26
-rw-r--r--usr.bin/ssh/cipher.c47
-rw-r--r--usr.bin/ssh/cipher.h29
-rw-r--r--usr.bin/ssh/kex.c15
-rw-r--r--usr.bin/ssh/kex.h4
-rw-r--r--usr.bin/ssh/packet.c52
6 files changed, 104 insertions, 69 deletions
diff --git a/usr.bin/ssh/authfile.c b/usr.bin/ssh/authfile.c
index 87c4c6cbbdf..772ee940194 100644
--- a/usr.bin/ssh/authfile.c
+++ b/usr.bin/ssh/authfile.c
@@ -36,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: authfile.c,v 1.45 2001/12/29 21:56:01 stevesk Exp $");
+RCSID("$OpenBSD: authfile.c,v 1.46 2002/02/14 23:41:01 markus Exp $");
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -69,7 +69,7 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
{
Buffer buffer, encrypted;
u_char buf[100], *cp;
- int fd, i;
+ int fd, i, cipher_num;
CipherContext ciphercontext;
Cipher *cipher;
u_int32_t rand;
@@ -78,11 +78,9 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
*/
- if (strcmp(passphrase, "") == 0)
- cipher = cipher_by_number(SSH_CIPHER_NONE);
- else
- cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
- if (cipher == NULL)
+ cipher_num = (strcmp(passphrase, "") == 0) ?
+ SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
+ if ((cipher = cipher_by_number(cipher_num)) == NULL)
fatal("save_private_key_rsa: bad cipher");
/* This buffer is used to built the secret part of the private key. */
@@ -119,7 +117,7 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
buffer_put_char(&encrypted, 0);
/* Store cipher type. */
- buffer_put_char(&encrypted, cipher->number);
+ buffer_put_char(&encrypted, cipher_num);
buffer_put_int(&encrypted, 0); /* For future extension */
/* Store public key. This will be in plain text. */
@@ -131,9 +129,11 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
/* Allocate space for the private part of the key in the buffer. */
cp = buffer_append_space(&encrypted, buffer_len(&buffer));
- cipher_set_key_string(&ciphercontext, cipher, passphrase);
- cipher_encrypt(&ciphercontext, cp,
+ cipher_set_key_string(&ciphercontext, cipher, passphrase,
+ CIPHER_ENCRYPT);
+ cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
+ cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
/* Destroy temporary data. */
@@ -380,9 +380,11 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
cp = buffer_append_space(&decrypted, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- cipher_set_key_string(&ciphercontext, cipher, passphrase);
- cipher_decrypt(&ciphercontext, cp,
+ cipher_set_key_string(&ciphercontext, cipher, passphrase,
+ CIPHER_DECRYPT);
+ cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
+ cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&buffer);
diff --git a/usr.bin/ssh/cipher.c b/usr.bin/ssh/cipher.c
index 58b0e8aa78e..c31696cee20 100644
--- a/usr.bin/ssh/cipher.c
+++ b/usr.bin/ssh/cipher.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.50 2002/01/21 22:30:12 markus Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.51 2002/02/14 23:41:01 markus Exp $");
#include "xmalloc.h"
#include "log.h"
@@ -43,6 +43,17 @@ RCSID("$OpenBSD: cipher.c,v 1.50 2002/01/21 22:30:12 markus Exp $");
#include <openssl/md5.h>
+struct Cipher {
+ char *name;
+ int number; /* for ssh1 only */
+ u_int block_size;
+ u_int key_len;
+ void (*setkey)(CipherContext *, const u_char *, u_int);
+ void (*setiv)(CipherContext *, const u_char *, u_int);
+ void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int);
+ void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
+};
+
/* no encryption */
static void
none_setkey(CipherContext *cc, const u_char *key, u_int keylen)
@@ -397,6 +408,18 @@ Cipher ciphers[] = {
/*--*/
+u_int
+cipher_blocksize(Cipher *c)
+{
+ return (c->block_size);
+}
+
+u_int
+cipher_keylen(Cipher *c)
+{
+ return (c->key_len);
+}
+
u_int
cipher_mask_ssh1(int client)
{
@@ -479,8 +502,8 @@ cipher_name(int id)
}
void
-cipher_init(CipherContext *cc, Cipher *cipher,
- const u_char *key, u_int keylen, const u_char *iv, u_int ivlen)
+cipher_init(CipherContext *cc, Cipher *cipher, const u_char *key,
+ u_int keylen, const u_char *iv, u_int ivlen, int encrypt)
{
if (keylen < cipher->key_len)
fatal("cipher_init: key length %d is insufficient for %s.",
@@ -489,24 +512,26 @@ cipher_init(CipherContext *cc, Cipher *cipher,
fatal("cipher_init: iv length %d is insufficient for %s.",
ivlen, cipher->name);
cc->cipher = cipher;
+ cc->encrypt = (encrypt == CIPHER_ENCRYPT);
cipher->setkey(cc, key, keylen);
cipher->setiv(cc, iv, ivlen);
}
void
-cipher_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
{
if (len % cc->cipher->block_size)
fatal("cipher_encrypt: bad plaintext length %d", len);
- cc->cipher->encrypt(cc, dest, src, len);
+ if (cc->encrypt)
+ cc->cipher->encrypt(cc, dest, src, len);
+ else
+ cc->cipher->decrypt(cc, dest, src, len);
}
void
-cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+cipher_cleanup(CipherContext *cc)
{
- if (len % cc->cipher->block_size)
- fatal("cipher_decrypt: bad ciphertext length %d", len);
- cc->cipher->decrypt(cc, dest, src, len);
+ memset(cc, 0, sizeof(*cc));
}
/*
@@ -516,7 +541,7 @@ cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
void
cipher_set_key_string(CipherContext *cc, Cipher *cipher,
- const char *passphrase)
+ const char *passphrase, int encrypt)
{
MD5_CTX md;
u_char digest[16];
@@ -525,7 +550,7 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher,
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
- cipher_init(cc, cipher, digest, 16, NULL, 0);
+ cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
diff --git a/usr.bin/ssh/cipher.h b/usr.bin/ssh/cipher.h
index 4533f5e4c20..0c412b47f95 100644
--- a/usr.bin/ssh/cipher.h
+++ b/usr.bin/ssh/cipher.h
@@ -32,7 +32,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* RCSID("$OpenBSD: cipher.h,v 1.29 2001/08/23 11:31:59 markus Exp $"); */
+/* RCSID("$OpenBSD: cipher.h,v 1.30 2002/02/14 23:41:01 markus Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
@@ -59,9 +59,13 @@
#define SSH_CIPHER_RESERVED 7
#define SSH_CIPHER_MAX 31
+#define CIPHER_ENCRYPT 1
+#define CIPHER_DECRYPT 0
+
typedef struct Cipher Cipher;
typedef struct CipherContext CipherContext;
+struct Cipher;
struct CipherContext {
union {
struct {
@@ -91,18 +95,10 @@ struct CipherContext {
} rijndael;
RC4_KEY rc4;
} u;
+ int plaintext;
+ int encrypt;
Cipher *cipher;
};
-struct Cipher {
- char *name;
- int number; /* for ssh1 only */
- u_int block_size;
- u_int key_len;
- void (*setkey)(CipherContext *, const u_char *, u_int);
- void (*setiv)(CipherContext *, const u_char *, u_int);
- void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int);
- void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
-};
u_int cipher_mask_ssh1(int);
Cipher *cipher_by_name(const char *);
@@ -111,9 +107,10 @@ int cipher_number(const char *);
char *cipher_name(int);
int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
- const u_char *, u_int);
-void cipher_encrypt(CipherContext *, u_char *, const u_char *, u_int);
-void cipher_decrypt(CipherContext *, u_char *, const u_char *, u_int);
-void cipher_set_key_string(CipherContext *, Cipher *, const char *);
-
+ const u_char *, u_int, int);
+void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
+void cipher_cleanup(CipherContext *);
+void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
+u_int cipher_blocksize(Cipher *);
+u_int cipher_keylen(Cipher *);
#endif /* CIPHER_H */
diff --git a/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c
index 02c9780ad1d..e9f944b05ba 100644
--- a/usr.bin/ssh/kex.c
+++ b/usr.bin/ssh/kex.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.44 2002/02/11 16:10:15 markus Exp $");
+RCSID("$OpenBSD: kex.c,v 1.45 2002/02/14 23:41:01 markus Exp $");
#include <openssl/crypto.h>
@@ -232,13 +232,14 @@ choose_enc(Enc *enc, char *client, char *server)
char *name = match_list(client, server, NULL);
if (name == NULL)
fatal("no matching cipher found: client %s server %s", client, server);
- enc->cipher = cipher_by_name(name);
- if (enc->cipher == NULL)
+ if ((enc->cipher = cipher_by_name(name)) == NULL)
fatal("matching cipher is not supported: %s", name);
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
enc->key = NULL;
+ enc->key_len = cipher_keylen(enc->cipher);
+ enc->block_size = cipher_blocksize(enc->cipher);
}
static void
choose_mac(Mac *mac, char *client, char *server)
@@ -341,10 +342,10 @@ kex_choose_conf(Kex *kex)
need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
newkeys = kex->newkeys[mode];
- if (need < newkeys->enc.cipher->key_len)
- need = newkeys->enc.cipher->key_len;
- if (need < newkeys->enc.cipher->block_size)
- need = newkeys->enc.cipher->block_size;
+ if (need < newkeys->enc.key_len)
+ need = newkeys->enc.key_len;
+ if (need < newkeys->enc.block_size)
+ need = newkeys->enc.block_size;
if (need < newkeys->mac.key_len)
need = newkeys->mac.key_len;
}
diff --git a/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h
index 7bd6bc2159b..755bf332aa4 100644
--- a/usr.bin/ssh/kex.h
+++ b/usr.bin/ssh/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.28 2001/12/28 15:06:00 markus Exp $ */
+/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -71,6 +71,8 @@ struct Enc {
char *name;
Cipher *cipher;
int enabled;
+ u_int key_len;
+ u_int block_size;
u_char *key;
u_char *iv;
};
diff --git a/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c
index 62681232b46..accd49061fc 100644
--- a/usr.bin/ssh/packet.c
+++ b/usr.bin/ssh/packet.c
@@ -37,7 +37,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.87 2002/01/24 21:13:23 stevesk Exp $");
+RCSID("$OpenBSD: packet.c,v 1.88 2002/02/14 23:41:01 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@@ -131,8 +131,8 @@ packet_set_connection(int fd_in, int fd_out)
fatal("packet_set_connection: cannot load cipher 'none'");
connection_in = fd_in;
connection_out = fd_out;
- cipher_init(&send_context, none, "", 0, NULL, 0);
- cipher_init(&receive_context, none, "", 0, NULL, 0);
+ cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT);
+ cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
if (!initialized) {
initialized = 1;
@@ -241,6 +241,8 @@ packet_close(void)
buffer_free(&compression_buffer);
buffer_compress_uninit();
}
+ cipher_cleanup(&send_context);
+ cipher_cleanup(&receive_context);
}
/* Sets remote side protocol flags. */
@@ -298,8 +300,8 @@ packet_set_encryption_key(const u_char *key, u_int keylen,
fatal("packet_set_encryption_key: unknown cipher number %d", number);
if (keylen < 20)
fatal("packet_set_encryption_key: keylen too small: %d", keylen);
- cipher_init(&receive_context, cipher, key, keylen, NULL, 0);
- cipher_init(&send_context, cipher, key, keylen, NULL, 0);
+ cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
+ cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
}
/* Start constructing a packet to send. */
@@ -388,7 +390,7 @@ packet_send1(void)
/* Insert padding. Initialized to zero in packet_start1() */
padding = 8 - len % 8;
- if (send_context.cipher->number != SSH_CIPHER_NONE) {
+ if (!send_context.plaintext) {
cp = buffer_ptr(&outgoing_packet);
for (i = 0; i < padding; i++) {
if (i % 4 == 0)
@@ -414,7 +416,7 @@ packet_send1(void)
PUT_32BIT(buf, len);
buffer_append(&output, buf, 4);
cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
- cipher_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
+ cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
buffer_len(&outgoing_packet));
#ifdef PACKET_DEBUG
@@ -438,14 +440,20 @@ set_newkeys(int mode)
Mac *mac;
Comp *comp;
CipherContext *cc;
+ int encrypt;
debug("newkeys: mode %d", mode);
- cc = (mode == MODE_OUT) ? &send_context : &receive_context;
+ if (mode == MODE_OUT) {
+ cc = &send_context;
+ encrypt = CIPHER_ENCRYPT;
+ } else {
+ cc = &receive_context;
+ encrypt = CIPHER_DECRYPT;
+ }
if (newkeys[mode] != NULL) {
debug("newkeys: rekeying");
- /* todo: free old keys, reset compression/cipher-ctxt; */
- memset(cc, 0, sizeof(*cc));
+ cipher_cleanup(cc);
enc = &newkeys[mode]->enc;
mac = &newkeys[mode]->mac;
comp = &newkeys[mode]->comp;
@@ -467,10 +475,10 @@ set_newkeys(int mode)
if (mac->md != NULL)
mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode));
- cipher_init(cc, enc->cipher, enc->key, enc->cipher->key_len,
- enc->iv, enc->cipher->block_size);
- memset(enc->iv, 0, enc->cipher->block_size);
- memset(enc->key, 0, enc->cipher->key_len);
+ cipher_init(cc, enc->cipher, enc->key, enc->key_len,
+ enc->iv, enc->block_size, encrypt);
+ memset(enc->iv, 0, enc->block_size);
+ memset(enc->key, 0, enc->key_len);
if (comp->type != 0 && comp->enabled == 0) {
packet_init_compression();
if (mode == MODE_OUT)
@@ -504,7 +512,7 @@ packet_send2(void)
mac = &newkeys[MODE_OUT]->mac;
comp = &newkeys[MODE_OUT]->comp;
}
- block_size = enc ? enc->cipher->block_size : 8;
+ block_size = enc ? enc->block_size : 8;
ucp = buffer_ptr(&outgoing_packet);
type = ucp[5];
@@ -548,7 +556,7 @@ packet_send2(void)
extra_pad = 0;
}
cp = buffer_append_space(&outgoing_packet, padlen);
- if (enc && enc->cipher->number != SSH_CIPHER_NONE) {
+ if (enc && !send_context.plaintext) {
/* random padding */
for (i = 0; i < padlen; i++) {
if (i % 4 == 0)
@@ -576,7 +584,7 @@ packet_send2(void)
}
/* encrypt packet and append to output buffer. */
cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
- cipher_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
+ cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
buffer_len(&outgoing_packet));
/* append unencrypted MAC */
if (mac && mac->enabled)
@@ -729,14 +737,14 @@ packet_read_poll1(void)
* (C)1998 CORE-SDI, Buenos Aires Argentina
* Ariel Futoransky(futo@core-sdi.com)
*/
- if (receive_context.cipher->number != SSH_CIPHER_NONE &&
+ if (!receive_context.plaintext &&
detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)
packet_disconnect("crc32 compensation attack: network attack detected");
/* Decrypt data to incoming_packet. */
buffer_clear(&incoming_packet);
cp = buffer_append_space(&incoming_packet, padded_len);
- cipher_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
+ cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
buffer_consume(&input, padded_len);
@@ -793,7 +801,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
comp = &newkeys[MODE_IN]->comp;
}
maclen = mac && mac->enabled ? mac->mac_len : 0;
- block_size = enc ? enc->cipher->block_size : 8;
+ block_size = enc ? enc->block_size : 8;
if (packet_length == 0) {
/*
@@ -804,7 +812,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
return SSH_MSG_NONE;
buffer_clear(&incoming_packet);
cp = buffer_append_space(&incoming_packet, block_size);
- cipher_decrypt(&receive_context, cp, buffer_ptr(&input),
+ cipher_crypt(&receive_context, cp, buffer_ptr(&input),
block_size);
ucp = buffer_ptr(&incoming_packet);
packet_length = GET_32BIT(ucp);
@@ -833,7 +841,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
buffer_dump(&input);
#endif
cp = buffer_append_space(&incoming_packet, need);
- cipher_decrypt(&receive_context, cp, buffer_ptr(&input), need);
+ cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
buffer_consume(&input, need);
/*
* compute MAC over seqnr and packet,