upstream commit

small refactor of cipher.c: make ciphercontext opaque to
callers feedback and ok markus@

Upstream-ID: 094849f8be68c3bdad2c0f3dee551ecf7be87f6f
This commit is contained in:
djm@openbsd.org 2016-08-03 05:41:57 +00:00 committed by Darren Tucker
parent e600348a7a
commit 4706c1d8c1
5 changed files with 179 additions and 139 deletions

View File

@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $OpenBSD: cipher-chachapoly.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */ /* $OpenBSD: cipher-chachapoly.c,v 1.8 2016/08/03 05:41:57 djm Exp $ */
#include "includes.h" #include "includes.h"
@ -28,7 +28,8 @@
#include "ssherr.h" #include "ssherr.h"
#include "cipher-chachapoly.h" #include "cipher-chachapoly.h"
int chachapoly_init(struct chachapoly_ctx *ctx, int
chachapoly_init(struct chachapoly_ctx *ctx,
const u_char *key, u_int keylen) const u_char *key, u_int keylen)
{ {
if (keylen != (32 + 32)) /* 2 x 256 bit keys */ if (keylen != (32 + 32)) /* 2 x 256 bit keys */

165
cipher.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.c,v 1.101 2015/12/10 17:08:40 mmcc Exp $ */ /* $OpenBSD: cipher.c,v 1.102 2016/08/03 05:41:57 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -57,6 +57,15 @@ extern const EVP_CIPHER *evp_ssh1_3des(void);
extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
#endif #endif
struct sshcipher_ctx {
int plaintext;
int encrypt;
EVP_CIPHER_CTX *evp;
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
struct aesctr_ctx ac_ctx; /* XXX union with evp? */
const struct sshcipher *cipher;
};
struct sshcipher { struct sshcipher {
char *name; char *name;
int number; /* for ssh1 only */ int number; /* for ssh1 only */
@ -205,6 +214,18 @@ cipher_is_cbc(const struct sshcipher *c)
return (c->flags & CFLAG_CBC) != 0; return (c->flags & CFLAG_CBC) != 0;
} }
u_int
cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
{
return cc->plaintext;
}
u_int
cipher_ctx_get_number(struct sshcipher_ctx *cc)
{
return cc->cipher->number;
}
u_int u_int
cipher_mask_ssh1(int client) cipher_mask_ssh1(int client)
{ {
@ -297,65 +318,81 @@ cipher_warning_message(const struct sshcipher_ctx *cc)
} }
int int
cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher, cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
int do_encrypt) int do_encrypt)
{ {
#ifdef WITH_OPENSSL struct sshcipher_ctx *cc = NULL;
int ret = SSH_ERR_INTERNAL_ERROR; int ret = SSH_ERR_INTERNAL_ERROR;
#ifdef WITH_OPENSSL
const EVP_CIPHER *type; const EVP_CIPHER *type;
int klen; int klen;
u_char *junk, *discard; u_char *junk, *discard;
#endif
*ccp = NULL;
if ((cc = calloc(sizeof(*cc), 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if (cipher->number == SSH_CIPHER_DES) { if (cipher->number == SSH_CIPHER_DES) {
if (keylen > 8) if (keylen > 8)
keylen = 8; keylen = 8;
} }
#endif
cc->plaintext = (cipher->number == SSH_CIPHER_NONE); cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
cc->encrypt = do_encrypt; cc->encrypt = do_encrypt;
if (keylen < cipher->key_len || if (keylen < cipher->key_len ||
(iv != NULL && ivlen < cipher_ivlen(cipher))) (iv != NULL && ivlen < cipher_ivlen(cipher))) {
return SSH_ERR_INVALID_ARGUMENT; ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
cc->cipher = cipher; cc->cipher = cipher;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
return chachapoly_init(&cc->cp_ctx, key, keylen); ret = chachapoly_init(&cc->cp_ctx, key, keylen);
goto out;
} }
#ifndef WITH_OPENSSL #ifndef WITH_OPENSSL
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
aesctr_ivsetup(&cc->ac_ctx, iv); aesctr_ivsetup(&cc->ac_ctx, iv);
return 0; ret = 0;
goto out;
} }
if ((cc->cipher->flags & CFLAG_NONE) != 0) if ((cc->cipher->flags & CFLAG_NONE) != 0) {
return 0; ret = 0;
return SSH_ERR_INVALID_ARGUMENT; goto out;
#else }
ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
#else /* WITH_OPENSSL */
type = (*cipher->evptype)(); type = (*cipher->evptype)();
EVP_CIPHER_CTX_init(&cc->evp); if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT)) == 0) { (do_encrypt == CIPHER_ENCRYPT)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad; goto out;
} }
if (cipher_authlen(cipher) && if (cipher_authlen(cipher) &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
-1, (u_char *)iv)) { -1, (u_char *)iv)) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad; goto out;
} }
klen = EVP_CIPHER_CTX_key_length(&cc->evp); klen = EVP_CIPHER_CTX_key_length(cc->evp);
if (klen > 0 && keylen != (u_int)klen) { if (klen > 0 && keylen != (u_int)klen) {
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) { if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad; goto out;
} }
} }
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad; goto out;
} }
if (cipher->discard_len > 0) { if (cipher->discard_len > 0) {
@ -363,21 +400,34 @@ cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
(discard = malloc(cipher->discard_len)) == NULL) { (discard = malloc(cipher->discard_len)) == NULL) {
free(junk); free(junk);
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto bad; goto out;
} }
ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len); ret = EVP_Cipher(cc->evp, discard, junk, cipher->discard_len);
explicit_bzero(discard, cipher->discard_len); explicit_bzero(discard, cipher->discard_len);
free(junk); free(junk);
free(discard); free(discard);
if (ret != 1) { if (ret != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
bad: goto out;
EVP_CIPHER_CTX_cleanup(&cc->evp);
return ret;
} }
} }
#endif ret = 0;
return 0; #endif /* WITH_OPENSSL */
out:
if (ret == 0) {
/* success */
*ccp = cc;
} else {
if (cc != NULL) {
#ifdef WITH_OPENSSL
if (cc->evp != NULL)
EVP_CIPHER_CTX_free(cc->evp);
#endif /* WITH_OPENSSL */
explicit_bzero(cc, sizeof(*cc));
free(cc);
}
}
return ret;
} }
/* /*
@ -418,33 +468,33 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
if (authlen != cipher_authlen(cc->cipher)) if (authlen != cipher_authlen(cc->cipher))
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
/* increment IV */ /* increment IV */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
1, lastiv)) 1, lastiv))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
/* set tag on decyption */ /* set tag on decyption */
if (!cc->encrypt && if (!cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
authlen, (u_char *)src + aadlen + len)) authlen, (u_char *)src + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} }
if (aadlen) { if (aadlen) {
if (authlen && if (authlen &&
EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
memcpy(dest, src, aadlen); memcpy(dest, src, aadlen);
} }
if (len % cc->cipher->block_size) if (len % cc->cipher->block_size)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
len) < 0) len) < 0)
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
if (authlen) { if (authlen) {
/* compute tag (on encrypt) or verify tag (on decrypt) */ /* compute tag (on encrypt) or verify tag (on decrypt) */
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
return cc->encrypt ? return cc->encrypt ?
SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
if (cc->encrypt && if (cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
authlen, dest + aadlen + len)) authlen, dest + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} }
@ -466,20 +516,23 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
return 0; return 0;
} }
int void
cipher_cleanup(struct sshcipher_ctx *cc) cipher_free(struct sshcipher_ctx *cc)
{ {
if (cc == NULL || cc->cipher == NULL) if (cc == NULL)
return 0; return;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) if (cc->evp != NULL) {
return SSH_ERR_LIBCRYPTO_ERROR; EVP_CIPHER_CTX_free(cc->evp);
cc->evp = NULL;
}
#endif #endif
return 0; explicit_bzero(cc, sizeof(*cc));
free(cc);
} }
/* /*
@ -487,8 +540,8 @@ cipher_cleanup(struct sshcipher_ctx *cc)
* passphrase and using the resulting 16 bytes as the key. * passphrase and using the resulting 16 bytes as the key.
*/ */
int int
cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher, cipher_set_key_string(struct sshcipher_ctx **ccp,
const char *passphrase, int do_encrypt) const struct sshcipher *cipher, const char *passphrase, int do_encrypt)
{ {
u_char digest[16]; u_char digest[16];
int r = SSH_ERR_INTERNAL_ERROR; int r = SSH_ERR_INTERNAL_ERROR;
@ -498,7 +551,7 @@ cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
digest, sizeof(digest))) != 0) digest, sizeof(digest))) != 0)
goto out; goto out;
r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); r = cipher_init(ccp, cipher, digest, 16, NULL, 0, do_encrypt);
out: out:
explicit_bzero(digest, sizeof(digest)); explicit_bzero(digest, sizeof(digest));
return r; return r;
@ -523,7 +576,7 @@ cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
ivlen = sizeof(cc->ac_ctx.ctr); ivlen = sizeof(cc->ac_ctx.ctr);
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
else else
ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); ivlen = EVP_CIPHER_CTX_iv_length(cc->evp);
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
return (ivlen); return (ivlen);
} }
@ -555,7 +608,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
case SSH_CIPHER_SSH2: case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES: case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH: case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
if (evplen == 0) if (evplen == 0)
return 0; return 0;
else if (evplen < 0) else if (evplen < 0)
@ -568,16 +621,16 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
else else
#endif #endif
if (cipher_authlen(c)) { if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
len, iv)) len, iv))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} else } else
memcpy(iv, cc->evp.iv, len); memcpy(iv, cc->evp->iv, len);
break; break;
#endif #endif
#ifdef WITH_SSH1 #ifdef WITH_SSH1
case SSH_CIPHER_3DES: case SSH_CIPHER_3DES:
return ssh1_3des_iv(&cc->evp, 0, iv, 24); return ssh1_3des_iv(cc->evp, 0, iv, 24);
#endif #endif
default: default:
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
@ -603,21 +656,21 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
case SSH_CIPHER_SSH2: case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES: case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH: case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
if (evplen <= 0) if (evplen <= 0)
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
if (cipher_authlen(c)) { if (cipher_authlen(c)) {
/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, if (!EVP_CIPHER_CTX_ctrl(cc->evp,
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} else } else
memcpy(cc->evp.iv, iv, evplen); memcpy(cc->evp->iv, iv, evplen);
break; break;
#endif #endif
#ifdef WITH_SSH1 #ifdef WITH_SSH1
case SSH_CIPHER_3DES: case SSH_CIPHER_3DES:
return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); return ssh1_3des_iv(cc->evp, 1, (u_char *)iv, 24);
#endif #endif
default: default:
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
@ -626,8 +679,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
} }
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
#define EVP_X_STATE(evp) (evp).cipher_data #define EVP_X_STATE(evp) (evp)->cipher_data
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size #define EVP_X_STATE_LEN(evp) (evp)->cipher->ctx_size
#endif #endif
int int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.48 2015/07/08 19:09:25 markus Exp $ */ /* $OpenBSD: cipher.h,v 1.49 2016/08/03 05:41:57 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -63,14 +63,7 @@
#define CIPHER_DECRYPT 0 #define CIPHER_DECRYPT 0
struct sshcipher; struct sshcipher;
struct sshcipher_ctx { struct sshcipher_ctx;
int plaintext;
int encrypt;
EVP_CIPHER_CTX evp;
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
struct aesctr_ctx ac_ctx; /* XXX union with evp? */
const struct sshcipher *cipher;
};
u_int cipher_mask_ssh1(int); u_int cipher_mask_ssh1(int);
const struct sshcipher *cipher_by_name(const char *); const struct sshcipher *cipher_by_name(const char *);
@ -80,15 +73,15 @@ char *cipher_name(int);
const char *cipher_warning_message(const struct sshcipher_ctx *); const char *cipher_warning_message(const struct sshcipher_ctx *);
int ciphers_valid(const char *); int ciphers_valid(const char *);
char *cipher_alg_list(char, int); char *cipher_alg_list(char, int);
int cipher_init(struct sshcipher_ctx *, const struct sshcipher *, int cipher_init(struct sshcipher_ctx **, const struct sshcipher *,
const u_char *, u_int, const u_char *, u_int, int); const u_char *, u_int, const u_char *, u_int, int);
int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
u_int, u_int, u_int); u_int, u_int, u_int);
int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
const u_char *, u_int); const u_char *, u_int);
int cipher_cleanup(struct sshcipher_ctx *); void cipher_free(struct sshcipher_ctx *);
int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *, int cipher_set_key_string(struct sshcipher_ctx **,
const char *, int); const struct sshcipher *, const char *, int);
u_int cipher_blocksize(const struct sshcipher *); u_int cipher_blocksize(const struct sshcipher *);
u_int cipher_keylen(const struct sshcipher *); u_int cipher_keylen(const struct sshcipher *);
u_int cipher_seclen(const struct sshcipher *); u_int cipher_seclen(const struct sshcipher *);
@ -96,10 +89,14 @@ u_int cipher_authlen(const struct sshcipher *);
u_int cipher_ivlen(const struct sshcipher *); u_int cipher_ivlen(const struct sshcipher *);
u_int cipher_is_cbc(const struct sshcipher *); u_int cipher_is_cbc(const struct sshcipher *);
u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *);
u_int cipher_ctx_get_number(struct sshcipher_ctx *);
u_int cipher_get_number(const struct sshcipher *); u_int cipher_get_number(const struct sshcipher *);
int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int); int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *); int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
int cipher_get_keyiv_len(const struct sshcipher_ctx *); int cipher_get_keyiv_len(const struct sshcipher_ctx *);
int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *); int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *); void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
#endif /* CIPHER_H */ #endif /* CIPHER_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.234 2016/07/18 11:35:33 markus Exp $ */ /* $OpenBSD: packet.c,v 1.235 2016/08/03 05:41:57 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -122,10 +122,10 @@ struct session_state {
u_int remote_protocol_flags; u_int remote_protocol_flags;
/* Encryption context for receiving data. Only used for decryption. */ /* Encryption context for receiving data. Only used for decryption. */
struct sshcipher_ctx receive_context; struct sshcipher_ctx *receive_context;
/* Encryption context for sending data. Only used for encryption. */ /* Encryption context for sending data. Only used for encryption. */
struct sshcipher_ctx send_context; struct sshcipher_ctx *send_context;
/* Buffer for raw input data from the socket. */ /* Buffer for raw input data from the socket. */
struct sshbuf *input; struct sshbuf *input;
@ -529,7 +529,6 @@ void
ssh_packet_close(struct ssh *ssh) ssh_packet_close(struct ssh *ssh)
{ {
struct session_state *state = ssh->state; struct session_state *state = ssh->state;
int r;
u_int mode; u_int mode;
if (!state->initialized) if (!state->initialized)
@ -573,10 +572,9 @@ ssh_packet_close(struct ssh *ssh)
inflateEnd(stream); inflateEnd(stream);
} }
} }
if ((r = cipher_cleanup(&state->send_context)) != 0) cipher_free(state->send_context);
error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); cipher_free(state->receive_context);
if ((r = cipher_cleanup(&state->receive_context)) != 0) state->send_context = state->receive_context = NULL;
error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
free(ssh->remote_ipaddr); free(ssh->remote_ipaddr);
ssh->remote_ipaddr = NULL; ssh->remote_ipaddr = NULL;
free(ssh->state); free(ssh->state);
@ -870,8 +868,8 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen,
NULL, 0, CIPHER_DECRYPT) != 0)) NULL, 0, CIPHER_DECRYPT) != 0))
fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
if (!state->cipher_warning_done && if (!state->cipher_warning_done &&
((wmsg = cipher_warning_message(&state->send_context)) != NULL || ((wmsg = cipher_warning_message(state->send_context)) != NULL ||
(wmsg = cipher_warning_message(&state->send_context)) != NULL)) { (wmsg = cipher_warning_message(state->send_context)) != NULL)) {
error("Warning: %s", wmsg); error("Warning: %s", wmsg);
state->cipher_warning_done = 1; state->cipher_warning_done = 1;
} }
@ -917,7 +915,7 @@ ssh_packet_send1(struct ssh *ssh)
/* Insert padding. Initialized to zero in packet_start1() */ /* Insert padding. Initialized to zero in packet_start1() */
padding = 8 - len % 8; padding = 8 - len % 8;
if (!state->send_context.plaintext) { if (!cipher_ctx_is_plaintext(state->send_context)) {
cp = sshbuf_mutable_ptr(state->outgoing_packet); cp = sshbuf_mutable_ptr(state->outgoing_packet);
if (cp == NULL) { if (cp == NULL) {
r = SSH_ERR_INTERNAL_ERROR; r = SSH_ERR_INTERNAL_ERROR;
@ -947,7 +945,7 @@ ssh_packet_send1(struct ssh *ssh)
if ((r = sshbuf_reserve(state->output, if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet), &cp)) != 0) sshbuf_len(state->outgoing_packet), &cp)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&state->send_context, 0, cp, if ((r = cipher_crypt(state->send_context, 0, cp,
sshbuf_ptr(state->outgoing_packet), sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet), 0, 0)) != 0) sshbuf_len(state->outgoing_packet), 0, 0)) != 0)
goto out; goto out;
@ -978,7 +976,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
struct sshenc *enc; struct sshenc *enc;
struct sshmac *mac; struct sshmac *mac;
struct sshcomp *comp; struct sshcomp *comp;
struct sshcipher_ctx *cc; struct sshcipher_ctx **ccp;
u_int64_t *max_blocks; u_int64_t *max_blocks;
const char *wmsg; const char *wmsg;
int r, crypt_type; int r, crypt_type;
@ -986,12 +984,12 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
debug2("set_newkeys: mode %d", mode); debug2("set_newkeys: mode %d", mode);
if (mode == MODE_OUT) { if (mode == MODE_OUT) {
cc = &state->send_context; ccp = &state->send_context;
crypt_type = CIPHER_ENCRYPT; crypt_type = CIPHER_ENCRYPT;
state->p_send.packets = state->p_send.blocks = 0; state->p_send.packets = state->p_send.blocks = 0;
max_blocks = &state->max_blocks_out; max_blocks = &state->max_blocks_out;
} else { } else {
cc = &state->receive_context; ccp = &state->receive_context;
crypt_type = CIPHER_DECRYPT; crypt_type = CIPHER_DECRYPT;
state->p_read.packets = state->p_read.blocks = 0; state->p_read.packets = state->p_read.blocks = 0;
max_blocks = &state->max_blocks_in; max_blocks = &state->max_blocks_in;
@ -1003,8 +1001,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
(unsigned long long)state->p_read.blocks, (unsigned long long)state->p_read.blocks,
(unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.bytes,
(unsigned long long)state->p_send.blocks); (unsigned long long)state->p_send.blocks);
if ((r = cipher_cleanup(cc)) != 0) cipher_free(*ccp);
return r; *ccp = NULL;
enc = &state->newkeys[mode]->enc; enc = &state->newkeys[mode]->enc;
mac = &state->newkeys[mode]->mac; mac = &state->newkeys[mode]->mac;
comp = &state->newkeys[mode]->comp; comp = &state->newkeys[mode]->comp;
@ -1033,11 +1031,11 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
} }
mac->enabled = 1; mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode)); DBG(debug("cipher_init_context: %d", mode));
if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->iv_len, crypt_type)) != 0) enc->iv, enc->iv_len, crypt_type)) != 0)
return r; return r;
if (!state->cipher_warning_done && if (!state->cipher_warning_done &&
(wmsg = cipher_warning_message(cc)) != NULL) { (wmsg = cipher_warning_message(*ccp)) != NULL) {
error("Warning: %s", wmsg); error("Warning: %s", wmsg);
state->cipher_warning_done = 1; state->cipher_warning_done = 1;
} }
@ -1259,7 +1257,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
} }
if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
goto out; goto out;
if (enc && !state->send_context.plaintext) { if (enc && !cipher_ctx_is_plaintext(state->send_context)) {
/* random padding */ /* random padding */
arc4random_buf(cp, padlen); arc4random_buf(cp, padlen);
} else { } else {
@ -1291,7 +1289,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
if ((r = sshbuf_reserve(state->output, if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp, if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp,
sshbuf_ptr(state->outgoing_packet), sshbuf_ptr(state->outgoing_packet),
len - aadlen, aadlen, authlen)) != 0) len - aadlen, aadlen, authlen)) != 0)
goto out; goto out;
@ -1606,7 +1604,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
* (C)1998 CORE-SDI, Buenos Aires Argentina * (C)1998 CORE-SDI, Buenos Aires Argentina
* Ariel Futoransky(futo@core-sdi.com) * Ariel Futoransky(futo@core-sdi.com)
*/ */
if (!state->receive_context.plaintext) { if (!cipher_ctx_is_plaintext(state->receive_context)) {
emsg = NULL; emsg = NULL;
switch (detect_attack(&state->deattack, switch (detect_attack(&state->deattack,
sshbuf_ptr(state->input), padded_len)) { sshbuf_ptr(state->input), padded_len)) {
@ -1635,7 +1633,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
sshbuf_reset(state->incoming_packet); sshbuf_reset(state->incoming_packet);
if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&state->receive_context, 0, p, if ((r = cipher_crypt(state->receive_context, 0, p,
sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) sshbuf_ptr(state->input), padded_len, 0, 0)) != 0)
goto out; goto out;
@ -1733,7 +1731,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
if (aadlen && state->packlen == 0) { if (aadlen && state->packlen == 0) {
if (cipher_get_length(&state->receive_context, if (cipher_get_length(state->receive_context,
&state->packlen, state->p_read.seqnr, &state->packlen, state->p_read.seqnr,
sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
return 0; return 0;
@ -1759,7 +1757,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_reserve(state->incoming_packet, block_size, if ((r = sshbuf_reserve(state->incoming_packet, block_size,
&cp)) != 0) &cp)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&state->receive_context, if ((r = cipher_crypt(state->receive_context,
state->p_send.seqnr, cp, sshbuf_ptr(state->input), state->p_send.seqnr, cp, sshbuf_ptr(state->input),
block_size, 0, 0)) != 0) block_size, 0, 0)) != 0)
goto out; goto out;
@ -1827,7 +1825,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
&cp)) != 0) &cp)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp, if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp,
sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) sshbuf_ptr(state->input), need, aadlen, authlen)) != 0)
goto out; goto out;
if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
@ -2509,8 +2507,8 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
enc = &newkey->enc; enc = &newkey->enc;
mac = &newkey->mac; mac = &newkey->mac;
comp = &newkey->comp; comp = &newkey->comp;
cc = (mode == MODE_OUT) ? &ssh->state->send_context : cc = (mode == MODE_OUT) ? ssh->state->send_context :
&ssh->state->receive_context; ssh->state->receive_context;
if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
return r; return r;
if ((b = sshbuf_new()) == NULL) if ((b = sshbuf_new()) == NULL)
@ -2549,18 +2547,18 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
int r, ssh1cipher; int r, ssh1cipher;
if (!compat20) { if (!compat20) {
ssh1cipher = cipher_get_number(state->receive_context.cipher); ssh1cipher = cipher_ctx_get_number(state->receive_context);
slen = cipher_get_keyiv_len(&state->send_context); slen = cipher_get_keyiv_len(state->send_context);
rlen = cipher_get_keyiv_len(&state->receive_context); rlen = cipher_get_keyiv_len(state->receive_context);
if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
(r = sshbuf_put_u32(m, ssh1cipher)) != 0 || (r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
(r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
(r = sshbuf_put_u32(m, slen)) != 0 || (r = sshbuf_put_u32(m, slen)) != 0 ||
(r = sshbuf_reserve(m, slen, &p)) != 0 || (r = sshbuf_reserve(m, slen, &p)) != 0 ||
(r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 || (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 ||
(r = sshbuf_put_u32(m, rlen)) != 0 || (r = sshbuf_put_u32(m, rlen)) != 0 ||
(r = sshbuf_reserve(m, rlen, &p)) != 0 || (r = sshbuf_reserve(m, rlen, &p)) != 0 ||
(r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0) (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0)
return r; return r;
} else { } else {
if ((r = kex_to_blob(m, ssh->kex)) != 0 || if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
@ -2579,17 +2577,17 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
return r; return r;
} }
slen = cipher_get_keycontext(&state->send_context, NULL); slen = cipher_get_keycontext(state->send_context, NULL);
rlen = cipher_get_keycontext(&state->receive_context, NULL); rlen = cipher_get_keycontext(state->receive_context, NULL);
if ((r = sshbuf_put_u32(m, slen)) != 0 || if ((r = sshbuf_put_u32(m, slen)) != 0 ||
(r = sshbuf_reserve(m, slen, &p)) != 0) (r = sshbuf_reserve(m, slen, &p)) != 0)
return r; return r;
if (cipher_get_keycontext(&state->send_context, p) != (int)slen) if (cipher_get_keycontext(state->send_context, p) != (int)slen)
return SSH_ERR_INTERNAL_ERROR; return SSH_ERR_INTERNAL_ERROR;
if ((r = sshbuf_put_u32(m, rlen)) != 0 || if ((r = sshbuf_put_u32(m, rlen)) != 0 ||
(r = sshbuf_reserve(m, rlen, &p)) != 0) (r = sshbuf_reserve(m, rlen, &p)) != 0)
return r; return r;
if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen) if (cipher_get_keycontext(state->receive_context, p) != (int)rlen)
return SSH_ERR_INTERNAL_ERROR; return SSH_ERR_INTERNAL_ERROR;
if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 || if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 ||
@ -2735,11 +2733,11 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
return SSH_ERR_KEY_UNKNOWN_CIPHER; return SSH_ERR_KEY_UNKNOWN_CIPHER;
ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
(int)ssh1cipher); (int)ssh1cipher);
if (cipher_get_keyiv_len(&state->send_context) != (int)slen || if (cipher_get_keyiv_len(state->send_context) != (int)slen ||
cipher_get_keyiv_len(&state->receive_context) != (int)rlen) cipher_get_keyiv_len(state->receive_context) != (int)rlen)
return SSH_ERR_INVALID_FORMAT; return SSH_ERR_INVALID_FORMAT;
if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 || if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 ||
(r = cipher_set_keyiv(&state->receive_context, ivin)) != 0) (r = cipher_set_keyiv(state->receive_context, ivin)) != 0)
return r; return r;
} else { } else {
if ((r = kex_from_blob(m, &ssh->kex)) != 0 || if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
@ -2769,11 +2767,11 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
(r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
return r; return r;
if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen || if (cipher_get_keycontext(state->send_context, NULL) != (int)slen ||
cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen) cipher_get_keycontext(state->receive_context, NULL) != (int)rlen)
return SSH_ERR_INVALID_FORMAT; return SSH_ERR_INVALID_FORMAT;
cipher_set_keycontext(&state->send_context, keyout); cipher_set_keycontext(state->send_context, keyout);
cipher_set_keycontext(&state->receive_context, keyin); cipher_set_keycontext(state->receive_context, keyin);
if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 || if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 ||
(r = ssh_packet_set_postauth(ssh)) != 0) (r = ssh_packet_set_postauth(ssh)) != 0)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshkey.c,v 1.35 2016/06/19 07:48:02 djm Exp $ */ /* $OpenBSD: sshkey.c,v 1.36 2016/08/03 05:41:57 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@ -3029,13 +3029,11 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
u_int check; u_int check;
int r = SSH_ERR_INTERNAL_ERROR; int r = SSH_ERR_INTERNAL_ERROR;
struct sshcipher_ctx ciphercontext; struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher; const struct sshcipher *cipher;
const char *kdfname = KDFNAME; const char *kdfname = KDFNAME;
struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL; struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
memset(&ciphercontext, 0, sizeof(ciphercontext));
if (rounds <= 0) if (rounds <= 0)
rounds = DEFAULT_ROUNDS; rounds = DEFAULT_ROUNDS;
if (passphrase == NULL || !strlen(passphrase)) { if (passphrase == NULL || !strlen(passphrase)) {
@ -3122,7 +3120,7 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
if ((r = sshbuf_reserve(encoded, if ((r = sshbuf_reserve(encoded,
sshbuf_len(encrypted) + authlen, &cp)) != 0) sshbuf_len(encrypted) + authlen, &cp)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&ciphercontext, 0, cp, if ((r = cipher_crypt(ciphercontext, 0, cp,
sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
goto out; goto out;
@ -3154,7 +3152,7 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
sshbuf_free(kdf); sshbuf_free(kdf);
sshbuf_free(encoded); sshbuf_free(encoded);
sshbuf_free(encrypted); sshbuf_free(encrypted);
cipher_cleanup(&ciphercontext); cipher_free(ciphercontext);
explicit_bzero(salt, sizeof(salt)); explicit_bzero(salt, sizeof(salt));
if (key != NULL) { if (key != NULL) {
explicit_bzero(key, keylen + ivlen); explicit_bzero(key, keylen + ivlen);
@ -3183,12 +3181,11 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0; size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
struct sshbuf *encoded = NULL, *decoded = NULL; struct sshbuf *encoded = NULL, *decoded = NULL;
struct sshbuf *kdf = NULL, *decrypted = NULL; struct sshbuf *kdf = NULL, *decrypted = NULL;
struct sshcipher_ctx ciphercontext; struct sshcipher_ctx *ciphercontext = NULL;
struct sshkey *k = NULL; struct sshkey *k = NULL;
u_char *key = NULL, *salt = NULL, *dp, pad, last; u_char *key = NULL, *salt = NULL, *dp, pad, last;
u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
memset(&ciphercontext, 0, sizeof(ciphercontext));
if (keyp != NULL) if (keyp != NULL)
*keyp = NULL; *keyp = NULL;
if (commentp != NULL) if (commentp != NULL)
@ -3317,7 +3314,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
(r = cipher_init(&ciphercontext, cipher, key, keylen, (r = cipher_init(&ciphercontext, cipher, key, keylen,
key + keylen, ivlen, 0)) != 0) key + keylen, ivlen, 0)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
encrypted_len, 0, authlen)) != 0) { encrypted_len, 0, authlen)) != 0) {
/* an integrity error here indicates an incorrect passphrase */ /* an integrity error here indicates an incorrect passphrase */
if (r == SSH_ERR_MAC_INVALID) if (r == SSH_ERR_MAC_INVALID)
@ -3371,7 +3368,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
} }
out: out:
pad = 0; pad = 0;
cipher_cleanup(&ciphercontext); cipher_free(ciphercontext);
free(ciphername); free(ciphername);
free(kdfname); free(kdfname);
free(comment); free(comment);
@ -3405,7 +3402,7 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
struct sshbuf *buffer = NULL, *encrypted = NULL; struct sshbuf *buffer = NULL, *encrypted = NULL;
u_char buf[8]; u_char buf[8];
int r, cipher_num; int r, cipher_num;
struct sshcipher_ctx ciphercontext; struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher; const struct sshcipher *cipher;
u_char *cp; u_char *cp;
@ -3475,16 +3472,14 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_ENCRYPT)) != 0) CIPHER_ENCRYPT)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&ciphercontext, 0, cp, if ((r = cipher_crypt(ciphercontext, 0, cp,
sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0)
goto out; goto out;
if ((r = cipher_cleanup(&ciphercontext)) != 0)
goto out;
r = sshbuf_putb(blob, encrypted); r = sshbuf_putb(blob, encrypted);
out: out:
explicit_bzero(&ciphercontext, sizeof(ciphercontext)); cipher_free(ciphercontext);
explicit_bzero(buf, sizeof(buf)); explicit_bzero(buf, sizeof(buf));
sshbuf_free(buffer); sshbuf_free(buffer);
sshbuf_free(encrypted); sshbuf_free(encrypted);
@ -3654,7 +3649,7 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
struct sshbuf *decrypted = NULL, *copy = NULL; struct sshbuf *decrypted = NULL, *copy = NULL;
u_char *cp; u_char *cp;
char *comment = NULL; char *comment = NULL;
struct sshcipher_ctx ciphercontext; struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher; const struct sshcipher *cipher;
struct sshkey *prv = NULL; struct sshkey *prv = NULL;
@ -3712,12 +3707,8 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT)) != 0) CIPHER_DECRYPT)) != 0)
goto out; goto out;
if ((r = cipher_crypt(&ciphercontext, 0, cp, if ((r = cipher_crypt(ciphercontext, 0, cp,
sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) { sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0)
cipher_cleanup(&ciphercontext);
goto out;
}
if ((r = cipher_cleanup(&ciphercontext)) != 0)
goto out; goto out;
if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
@ -3754,7 +3745,7 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
comment = NULL; comment = NULL;
} }
out: out:
explicit_bzero(&ciphercontext, sizeof(ciphercontext)); cipher_free(ciphercontext);
free(comment); free(comment);
sshkey_free(prv); sshkey_free(prv);
sshbuf_free(copy); sshbuf_free(copy);