defatal cipher.[ch]

unbreak arcfour(128|256)
This commit is contained in:
Damien Miller
2012-01-13 22:59:45 +11:00
committed by Markus Friedl
parent c037dfa962
commit ef0c2e123f
5 changed files with 219 additions and 156 deletions

View File

@@ -83,7 +83,7 @@ key_private_rsa1_to_blob(struct sshkey *key, Buffer *blob,
{
Buffer buffer, encrypted;
u_char buf[100], *cp;
int i, cipher_num;
int r, i, cipher_num;
CipherContext ciphercontext;
Cipher *cipher;
u_int32_t rnd;
@@ -143,11 +143,14 @@ key_private_rsa1_to_blob(struct sshkey *key, Buffer *blob,
/* 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);
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
cipher_cleanup(&ciphercontext);
if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_ENCRYPT)) != 0)
fatal("%s: cipher_set_key_string: %s", __func__, ssh_err(r));
if ((r = cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer))) != 0)
fatal("%s: cipher_crypt: %s", __func__, ssh_err(r));
if ((r = cipher_cleanup(&ciphercontext)) != 0)
fatal("%s: cipher_cleanup: %s", __func__, ssh_err(r));
memset(&ciphercontext, 0, sizeof(ciphercontext));
/* Destroy temporary data. */
@@ -410,7 +413,7 @@ key_load_public_type(int type, const char *filename, char **commentp)
static struct sshkey *
key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
{
int check1, check2, cipher_type;
int r, check1, check2, cipher_type;
Buffer decrypted;
u_char *cp;
CipherContext ciphercontext;
@@ -467,11 +470,14 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
cp = buffer_append_space(&decrypted, buffer_len(&copy));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT);
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&copy), buffer_len(&copy));
cipher_cleanup(&ciphercontext);
if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT)) != 0)
fatal("%s: cipher_set_key_string: %s", __func__, ssh_err(r));
if ((r = cipher_crypt(&ciphercontext, cp,
buffer_ptr(&copy), buffer_len(&copy))) != 0)
fatal("%s: cipher_crypt: %s", __func__, ssh_err(r));
if ((r = cipher_cleanup(&ciphercontext)) != 0)
fatal("%s: cipher_cleanup: %s", __func__, ssh_err(r));
memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&copy);

View File

@@ -42,8 +42,7 @@
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "log.h"
#include "err.h"
#include "cipher.h"
extern const EVP_CIPHER *evp_ssh1_bf(void);
@@ -52,7 +51,7 @@ 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 {
struct sshcipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
@@ -88,25 +87,25 @@ struct Cipher {
/*--*/
u_int
cipher_blocksize(const Cipher *c)
cipher_blocksize(const struct sshcipher *c)
{
return (c->block_size);
}
u_int
cipher_keylen(const Cipher *c)
cipher_keylen(const struct sshcipher *c)
{
return (c->key_len);
}
u_int
cipher_get_number(const Cipher *c)
cipher_get_number(const struct sshcipher *c)
{
return (c->number);
}
u_int
cipher_is_cbc(const Cipher *c)
cipher_is_cbc(const struct sshcipher *c)
{
return (c->cbc_mode);
}
@@ -123,20 +122,20 @@ cipher_mask_ssh1(int client)
return mask;
}
Cipher *
struct sshcipher *
cipher_by_name(const char *name)
{
Cipher *c;
struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++)
if (strcmp(c->name, name) == 0)
return c;
return NULL;
}
Cipher *
struct sshcipher *
cipher_by_number(int id)
{
Cipher *c;
struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++)
if (c->number == id)
return c;
@@ -147,26 +146,23 @@ cipher_by_number(int id)
int
ciphers_valid(const char *names)
{
Cipher *c;
struct sshcipher *c;
char *cipher_list, *cp;
char *p;
if (names == NULL || strcmp(names, "") == 0)
return 0;
cipher_list = cp = xstrdup(names);
if ((cipher_list = cp = strdup(names)) == NULL)
return 0;
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
(p = strsep(&cp, CIPHER_SEP))) {
c = cipher_by_name(p);
if (c == NULL || c->number != SSH_CIPHER_SSH2) {
debug("bad cipher %s [%s]", p, names);
xfree(cipher_list);
free(cipher_list);
return 0;
} else {
debug3("cipher ok: %s [%s]", p, names);
}
}
debug3("ciphers ok: [%s]", names);
xfree(cipher_list);
free(cipher_list);
return 1;
}
@@ -178,7 +174,7 @@ ciphers_valid(const char *names)
int
cipher_number(const char *name)
{
Cipher *c;
struct sshcipher *c;
if (name == NULL)
return -1;
for (c = ciphers; c->name != NULL; c++)
@@ -190,117 +186,136 @@ cipher_number(const char *name)
char *
cipher_name(int id)
{
Cipher *c = cipher_by_number(id);
struct sshcipher *c = cipher_by_number(id);
return (c==NULL) ? "<unknown>" : c->name;
}
void
cipher_init(CipherContext *cc, Cipher *cipher,
const char *
cipher_warning_message(struct sshcipher_ctx *cc)
{
if (cc == NULL || cc->cipher == NULL)
return NULL;
if (cc->cipher->number == SSH_CIPHER_DES)
return "use of DES is strongly discouraged due to "
"cryptographic weaknesses";
return NULL;
}
int
cipher_init(struct sshcipher_ctx *cc, struct sshcipher *cipher,
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
int do_encrypt)
{
static int dowarn = 1;
int ret = SSH_ERR_INTERNAL_ERROR;
const EVP_CIPHER *type;
int klen;
u_char *junk, *discard;
if (cipher->number == SSH_CIPHER_DES) {
if (dowarn) {
error("Warning: use of DES is strongly discouraged "
"due to cryptographic weaknesses");
dowarn = 0;
}
if (keylen > 8)
keylen = 8;
}
cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
if (keylen < cipher->key_len)
fatal("cipher_init: key length %d is insufficient for %s.",
keylen, cipher->name);
if (iv != NULL && ivlen < cipher->block_size)
fatal("cipher_init: iv length %d is insufficient for %s.",
ivlen, cipher->name);
if (keylen < cipher->key_len ||
(iv != NULL && ivlen < cipher->block_size))
return SSH_ERR_INVALID_ARGUMENT;
cc->cipher = cipher;
type = (*cipher->evptype)();
EVP_CIPHER_CTX_init(&cc->evp);
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT)) == 0)
fatal("cipher_init: EVP_CipherInit failed for %s",
cipher->name);
(do_encrypt == CIPHER_ENCRYPT)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
bad:
EVP_CIPHER_CTX_cleanup(&cc->evp);
return ret;
}
klen = EVP_CIPHER_CTX_key_length(&cc->evp);
if (klen > 0 && keylen != (u_int)klen) {
debug2("cipher_init: set keylen (%d -> %d)", klen, keylen);
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
fatal("cipher_init: set keylen failed (%d -> %d)",
klen, keylen);
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
}
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
fatal("cipher_init: EVP_CipherInit: set key failed for %s",
cipher->name);
if (cipher->discard_len > 0) {
junk = xmalloc(cipher->discard_len);
discard = xmalloc(cipher->discard_len);
if (EVP_Cipher(&cc->evp, discard, junk,
cipher->discard_len) == 0)
fatal("evp_crypt: EVP_Cipher failed during discard");
memset(discard, 0, cipher->discard_len);
xfree(junk);
xfree(discard);
if ((junk = malloc(cipher->discard_len)) == NULL ||
(discard = malloc(cipher->discard_len)) == NULL) {
if (junk != NULL)
free(junk);
ret = SSH_ERR_ALLOC_FAIL;
goto bad;
}
ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
bzero(discard, cipher->discard_len);
free(junk);
free(discard);
if (ret != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
}
return 0;
}
void
cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
int
cipher_crypt(struct sshcipher_ctx *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);
return SSH_ERR_INVALID_ARGUMENT;
if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
fatal("evp_crypt: EVP_Cipher failed");
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
void
cipher_cleanup(CipherContext *cc)
int
cipher_cleanup(struct sshcipher_ctx *cc)
{
if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
/*
* Selects the cipher, and keys if by computing the MD5 checksum of the
* passphrase and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext *cc, Cipher *cipher,
const char *passphrase, int do_encrypt)
int
cipher_set_key_string(struct sshcipher_ctx *cc, struct sshcipher *cipher,
const char *pphrase, int do_encrypt)
{
MD5_CTX md;
u_char digest[16];
int ret = SSH_ERR_LIBCRYPTO_ERROR;
MD5_Init(&md);
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
if (MD5_Init(&md) != 1 ||
MD5_Update(&md, (const u_char *)pphrase, strlen(pphrase)) != 1 ||
MD5_Final(digest, &md) != 1)
goto out;
cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
ret = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
out:
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
return ret;
}
/*
* Exports an IV from the CipherContext required to export the key
* Exports an IV from the sshcipher_ctx required to export the key
* state back from the unprivileged child to the privileged parent
* process.
*/
int
cipher_get_keyiv_len(const CipherContext *cc)
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
{
Cipher *c = cc->cipher;
struct sshcipher *c = cc->cipher;
int ivlen;
if (c->number == SSH_CIPHER_3DES)
@@ -310,10 +325,10 @@ cipher_get_keyiv_len(const CipherContext *cc)
return (ivlen);
}
void
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
int
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
{
Cipher *c = cc->cipher;
struct sshcipher *c = cc->cipher;
int evplen;
switch (c->number) {
@@ -321,11 +336,12 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen <= 0)
return;
if (evplen == 0)
break;
else if (evplen < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if ((u_int)evplen != len)
fatal("%s: wrong iv length %d != %d", __func__,
evplen, len);
return SSH_ERR_INVALID_ARGUMENT;
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
else
@@ -335,14 +351,15 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
ssh1_3des_iv(&cc->evp, 0, iv, 24);
break;
default:
fatal("%s: bad cipher %d", __func__, c->number);
return SSH_ERR_INVALID_ARGUMENT;
}
return 0;
}
void
cipher_set_keyiv(CipherContext *cc, u_char *iv)
int
cipher_set_keyiv(struct sshcipher_ctx *cc, u_char *iv)
{
Cipher *c = cc->cipher;
struct sshcipher *c = cc->cipher;
int evplen = 0;
switch (c->number) {
@@ -350,8 +367,8 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
if (evplen <= 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
else
@@ -361,17 +378,18 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
ssh1_3des_iv(&cc->evp, 1, iv, 24);
break;
default:
fatal("%s: bad cipher %d", __func__, c->number);
return SSH_ERR_INVALID_ARGUMENT;
}
return 0;
}
#define EVP_X_STATE(evp) (evp).cipher_data
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
int
cipher_get_keycontext(const CipherContext *cc, u_char *dat)
cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
{
Cipher *c = cc->cipher;
struct sshcipher *c = cc->cipher;
int plen = 0;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {
@@ -384,9 +402,9 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
}
void
cipher_set_keycontext(CipherContext *cc, u_char *dat)
cipher_set_keycontext(struct sshcipher_ctx *cc, u_char *dat)
{
Cipher *c = cc->cipher;
struct sshcipher *c = cc->cipher;
int plen;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {

View File

@@ -37,7 +37,9 @@
#ifndef CIPHER_H
#define CIPHER_H
#include <sys/types.h>
#include <openssl/evp.h>
/*
* Cipher types for SSH-1. New types can be added, but old types should not
* be removed for compatibility. The maximum allowed value is 31.
@@ -58,35 +60,38 @@
#define CIPHER_ENCRYPT 1
#define CIPHER_DECRYPT 0
typedef struct Cipher Cipher;
typedef struct CipherContext CipherContext;
typedef struct sshcipher Cipher;
typedef struct sshcipher_ctx CipherContext;
struct Cipher;
struct CipherContext {
struct sshcipher;
struct sshcipher_ctx {
int plaintext;
EVP_CIPHER_CTX evp;
Cipher *cipher;
};
u_int cipher_mask_ssh1(int);
Cipher *cipher_by_name(const char *);
Cipher *cipher_by_number(int);
struct sshcipher *cipher_by_name(const char *);
struct sshcipher *cipher_by_number(int);
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, 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(const Cipher *);
u_int cipher_keylen(const Cipher *);
u_int cipher_is_cbc(const Cipher *);
int cipher_init(struct sshcipher_ctx *, struct sshcipher *,
const u_char *, u_int, const u_char *, u_int, int);
const char* cipher_warning_message(struct sshcipher_ctx *);
int cipher_crypt(struct sshcipher_ctx *, u_char *, const u_char *, u_int);
int cipher_cleanup(struct sshcipher_ctx *);
int cipher_set_key_string(struct sshcipher_ctx *, struct sshcipher *,
const char *, int);
u_int cipher_blocksize(const struct sshcipher *);
u_int cipher_keylen(const struct sshcipher *);
u_int cipher_is_cbc(const struct sshcipher *);
u_int cipher_get_number(const struct sshcipher *);
int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
int cipher_set_keyiv(struct sshcipher_ctx *, u_char *);
int cipher_get_keyiv_len(const struct sshcipher_ctx *);
int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
void cipher_set_keycontext(struct sshcipher_ctx *, u_char *);
u_int cipher_get_number(const Cipher *);
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
void cipher_set_keyiv(CipherContext *, u_char *);
int cipher_get_keyiv_len(const CipherContext *);
int cipher_get_keycontext(const CipherContext *, u_char *);
void cipher_set_keycontext(CipherContext *, u_char *);
#endif /* CIPHER_H */

View File

@@ -245,9 +245,10 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
{
struct session_state *state;
Cipher *none = cipher_by_name("none");
int r;
if (none == NULL)
fatal("packet_set_connection: cannot load cipher 'none'");
fatal("%s: cannot load cipher 'none'", __func__);
if (ssh == NULL)
ssh = ssh_alloc_session_state();
if (ssh == NULL)
@@ -255,10 +256,11 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
state = ssh->state;
state->connection_in = fd_in;
state->connection_out = fd_out;
cipher_init(&state->send_context, none, (const u_char *)"",
0, NULL, 0, CIPHER_ENCRYPT);
cipher_init(&state->receive_context, none, (const u_char *)"",
0, NULL, 0, CIPHER_DECRYPT);
if ((r = cipher_init(&state->send_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
(r = cipher_init(&state->receive_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0)
fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
return ssh;
@@ -359,13 +361,15 @@ ssh_packet_get_keyiv(struct ssh *ssh, int mode, u_char *iv,
u_int len)
{
CipherContext *cc;
int r;
if (mode == MODE_OUT)
cc = &ssh->state->send_context;
else
cc = &ssh->state->receive_context;
cipher_get_keyiv(cc, iv, len);
if ((r = cipher_get_keyiv(cc, iv, len)) != 0)
fatal("%s: cipher_get_keyiv failed: %s", __func__, ssh_err(r));
}
int
@@ -411,13 +415,15 @@ void
ssh_packet_set_iv(struct ssh *ssh, int mode, u_char *dat)
{
CipherContext *cc;
int r;
if (mode == MODE_OUT)
cc = &ssh->state->send_context;
else
cc = &ssh->state->receive_context;
cipher_set_keyiv(cc, dat);
if ((r = cipher_set_keyiv(cc, dat)) != 0)
fatal("%s: cipher_set_keyiv failed: %s", __func__, ssh_err(r));
}
int
@@ -505,6 +511,7 @@ void
ssh_packet_close(struct ssh *ssh)
{
struct session_state *state = ssh->state;
int r;
if (!state->initialized)
return;
@@ -524,8 +531,9 @@ ssh_packet_close(struct ssh *ssh)
sshbuf_free(state->compression_buffer);
buffer_compress_uninit();
}
cipher_cleanup(&state->send_context);
cipher_cleanup(&state->receive_context);
if ((r = cipher_cleanup(&state->send_context)) != 0 ||
(r = cipher_cleanup(&state->receive_context)) != 0)
fatal("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
}
/* Sets remote side protocol flags. */
@@ -580,19 +588,28 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen,
{
struct session_state *state = ssh->state;
Cipher *cipher = cipher_by_number(number);
int r;
const char *wmsg;
if (cipher == NULL)
fatal("packet_set_encryption_key: unknown cipher number %d", number);
fatal("%s: unknown cipher number %d", __func__, number);
if (keylen < 20)
fatal("packet_set_encryption_key: keylen too small: %d", keylen);
fatal("%s: keylen too small: %d", __func__, keylen);
if (keylen > SSH_SESSION_KEY_LENGTH)
fatal("packet_set_encryption_key: keylen too big: %d", keylen);
fatal("%s: keylen too big: %d", __func__, keylen);
memcpy(state->ssh1_key, key, keylen);
state->ssh1_keylen = keylen;
cipher_init(&state->send_context, cipher, key, keylen, NULL,
0, CIPHER_ENCRYPT);
cipher_init(&state->receive_context, cipher, key, keylen, NULL,
0, CIPHER_DECRYPT);
if ((r = cipher_init(&state->send_context, cipher, key, keylen,
NULL, 0, CIPHER_ENCRYPT)) != 0 ||
(r = cipher_init(&state->receive_context, cipher, key, keylen,
NULL, 0, CIPHER_DECRYPT) != 0))
fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
if (!ssh->cipher_warning_done &&
((wmsg = cipher_warning_message(&state->send_context)) != NULL ||
(wmsg = cipher_warning_message(&state->send_context)) != NULL)) {
error("Warning: %s", wmsg);
ssh->cipher_warning_done = 1;
}
}
u_int
@@ -707,7 +724,7 @@ ssh_packet_send1(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char buf[8], *cp;
int i, padding, len, r;
int r, i, padding, len;
u_int checksum;
u_int32_t rnd = 0;
@@ -767,9 +784,10 @@ ssh_packet_send1(struct ssh *ssh)
if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet), &cp)) != 0)
goto out;
cipher_crypt(&state->send_context, cp,
if ((r = cipher_crypt(&state->send_context, cp,
sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet));
sshbuf_len(state->outgoing_packet))) != 0)
goto out;
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
@@ -799,7 +817,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
Comp *comp;
CipherContext *cc;
u_int64_t *max_blocks;
int crypt_type;
int crypt_type, r;
const char *wmsg;
debug2("set_newkeys: mode %d", mode);
@@ -816,7 +835,9 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
}
if (state->newkeys[mode] != NULL) {
debug("set_newkeys: rekeying");
cipher_cleanup(cc);
if ((r = cipher_cleanup(cc)) != 0)
fatal("%s: cipher_cleanup failed: %s",
__func__, ssh_err(r));
enc = &state->newkeys[mode]->enc;
mac = &state->newkeys[mode]->mac;
comp = &state->newkeys[mode]->comp;
@@ -838,8 +859,14 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
if (mac_init(mac) == 0)
mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode));
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, crypt_type);
if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, crypt_type)) != 0)
fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
if (!ssh->cipher_warning_done &&
(wmsg = cipher_warning_message(cc)) != NULL) {
error("Warning: %s", wmsg);
ssh->cipher_warning_done = 1;
}
/* Deleting the keys does not gain extra security */
/* memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len);
@@ -915,7 +942,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
Enc *enc = NULL;
Mac *mac = NULL;
Comp *comp = NULL;
int block_size, r;
int r, block_size;
if (state->newkeys[MODE_OUT] != NULL) {
enc = &state->newkeys[MODE_OUT]->enc;
@@ -1003,9 +1030,10 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet), &cp)) != 0)
goto out;
cipher_crypt(&state->send_context, cp,
if ((r = cipher_crypt(&state->send_context, cp,
sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet));
sshbuf_len(state->outgoing_packet))) != 0)
goto out;
/* append unencrypted MAC */
if (mac && mac->enabled)
if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0)
@@ -1287,8 +1315,9 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
sshbuf_reset(state->incoming_packet);
if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &cp)) != 0)
goto out;
cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), padded_len);
if ((r = cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), padded_len)) != 0)
goto out;
if ((r = sshbuf_consume(state->input, padded_len)) != 0)
goto out;
@@ -1376,8 +1405,9 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_reserve(state->incoming_packet, block_size,
&cp)) != 0)
goto out;
cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), block_size);
if ((r = cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), block_size)) != 0)
goto out;
cp = sshbuf_ptr(state->incoming_packet);
state->packlen = get_u32(cp);
if (state->packlen < 1 + 4 ||
@@ -1417,8 +1447,9 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
#endif
if ((r = sshbuf_reserve(state->incoming_packet, need, &cp)) != 0)
goto out;
cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), need);
if ((r = cipher_crypt(&state->receive_context, cp,
sshbuf_ptr(state->input), need)) != 0)
goto out;
if ((r = sshbuf_consume(state->input, need)) != 0)
goto out;
/*

View File

@@ -62,6 +62,9 @@ struct ssh {
/* Lists for private and public keys */
TAILQ_HEAD(, key_entry) private_keys;
TAILQ_HEAD(, key_entry) public_keys;
/* One-off warning about weak ciphers */
int cipher_warning_done;
};
struct ssh *ssh_alloc_session_state(void);