diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | authfile.c | 26 | ||||
-rw-r--r-- | cipher.c | 47 | ||||
-rw-r--r-- | cipher.h | 29 | ||||
-rw-r--r-- | kex.c | 15 | ||||
-rw-r--r-- | kex.h | 4 | ||||
-rw-r--r-- | packet.c | 52 |
7 files changed, 109 insertions, 70 deletions
@@ -13,6 +13,10 @@ [channels.h session.c ssh.c] increase the SSH v2 window size to 4 packets. comsumes a little bit more memory for slow receivers but increases througput. + - markus@cvs.openbsd.org 2002/02/14 23:41:01 + [authfile.c cipher.c cipher.h kex.c kex.h packet.c] + hide some more implementation details of cipher.[ch] and prepares for move + to EVP, ok deraadt@ 20020218 - (tim) newer config.guess from ftp://ftp.gnu.org/gnu/config/config.guess @@ -7610,4 +7614,4 @@ - Wrote replacements for strlcpy and mkdtemp - Released 1.0pre1 -$Id: ChangeLog,v 1.1857 2002/02/19 04:20:57 djm Exp $ +$Id: ChangeLog,v 1.1858 2002/02/19 04:21:23 djm Exp $ @@ -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); @@ -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)); @@ -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 */ @@ -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; } @@ -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; }; @@ -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, |