small refactor of cipher.c: make ciphercontext opaque to callers
authordjm <djm@openbsd.org>
Wed, 3 Aug 2016 05:41:57 +0000 (05:41 +0000)
committerdjm <djm@openbsd.org>
Wed, 3 Aug 2016 05:41:57 +0000 (05:41 +0000)
feedback and ok markus@

usr.bin/ssh/cipher-chachapoly.c
usr.bin/ssh/cipher.c
usr.bin/ssh/cipher.h
usr.bin/ssh/packet.c
usr.bin/ssh/sshkey.c

index 5f5d916..e5746dd 100644 (file)
@@ -14,7 +14,7 @@
  * 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 <sys/types.h>
 #include <stdarg.h> /* needed for log.h */
@@ -26,7 +26,8 @@
 #include "ssherr.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)
 {
        if (keylen != (32 + 32)) /* 2 x 256 bit keys */
index c4341e2..b4916a4 100644 (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>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -53,6 +53,15 @@ extern const EVP_CIPHER *evp_ssh1_3des(void);
 extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
 #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 {
        char    *name;
        int     number;         /* for ssh1 only */
@@ -191,6 +200,18 @@ cipher_is_cbc(const struct sshcipher *c)
        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
 cipher_mask_ssh1(int client)
 {
@@ -283,65 +304,81 @@ cipher_warning_message(const struct sshcipher_ctx *cc)
 }
 
 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,
     int do_encrypt)
 {
-#ifdef WITH_OPENSSL
+       struct sshcipher_ctx *cc = NULL;
        int ret = SSH_ERR_INTERNAL_ERROR;
+#ifdef WITH_OPENSSL
        const EVP_CIPHER *type;
        int klen;
        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 (keylen > 8)
                        keylen = 8;
        }
-#endif
+
        cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
        cc->encrypt = do_encrypt;
 
        if (keylen < cipher->key_len ||
-           (iv != NULL && ivlen < cipher_ivlen(cipher)))
-               return SSH_ERR_INVALID_ARGUMENT;
+           (iv != NULL && ivlen < cipher_ivlen(cipher))) {
+               ret = SSH_ERR_INVALID_ARGUMENT;
+               goto out;
+       }
 
        cc->cipher = cipher;
        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
        if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
                aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
                aesctr_ivsetup(&cc->ac_ctx, iv);
-               return 0;
+               ret = 0;
+               goto out;
        }
-       if ((cc->cipher->flags & CFLAG_NONE) != 0)
-               return 0;
-       return SSH_ERR_INVALID_ARGUMENT;
-#else
+       if ((cc->cipher->flags & CFLAG_NONE) != 0) {
+               ret = 0;
+               goto out;
+       }
+       ret = SSH_ERR_INVALID_ARGUMENT;
+       goto out;
+#else /* WITH_OPENSSL */
        type = (*cipher->evptype)();
-       EVP_CIPHER_CTX_init(&cc->evp);
-       if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
+       if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
+               ret = SSH_ERR_ALLOC_FAIL;
+               goto out;
+       }
+       if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
            (do_encrypt == CIPHER_ENCRYPT)) == 0) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
-               goto bad;
+               goto out;
        }
        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)) {
                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 (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;
-                       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;
-               goto bad;
+               goto out;
        }
 
        if (cipher->discard_len > 0) {
@@ -349,21 +386,34 @@ cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
                    (discard = malloc(cipher->discard_len)) == NULL) {
                        free(junk);
                        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);
                free(junk);
                free(discard);
                if (ret != 1) {
                        ret = SSH_ERR_LIBCRYPTO_ERROR;
- bad:
-                       EVP_CIPHER_CTX_cleanup(&cc->evp);
-                       return ret;
+                       goto out;
                }
        }
-#endif
-       return 0;
+       ret = 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;
 }
 
 /*
@@ -404,33 +454,33 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
                if (authlen != cipher_authlen(cc->cipher))
                        return SSH_ERR_INVALID_ARGUMENT;
                /* 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))
                        return SSH_ERR_LIBCRYPTO_ERROR;
                /* set tag on decyption */
                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))
                        return SSH_ERR_LIBCRYPTO_ERROR;
        }
        if (aadlen) {
                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;
                memcpy(dest, src, aadlen);
        }
        if (len % cc->cipher->block_size)
                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)
                return SSH_ERR_LIBCRYPTO_ERROR;
        if (authlen) {
                /* 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 ?
                            SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
                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))
                        return SSH_ERR_LIBCRYPTO_ERROR;
        }
@@ -452,20 +502,23 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
        return 0;
 }
 
-int
-cipher_cleanup(struct sshcipher_ctx *cc)
+void
+cipher_free(struct sshcipher_ctx *cc)
 {
-       if (cc == NULL || cc->cipher == NULL)
-               return 0;
+       if (cc == NULL)
+               return;
        if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
                explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
        else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
                explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
 #ifdef WITH_OPENSSL
-       else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
-               return SSH_ERR_LIBCRYPTO_ERROR;
+       if (cc->evp != NULL) {
+               EVP_CIPHER_CTX_free(cc->evp);
+               cc->evp = NULL;
+       }
 #endif
-       return 0;
+       explicit_bzero(cc, sizeof(*cc));
+       free(cc);
 }
 
 /*
@@ -473,8 +526,8 @@ cipher_cleanup(struct sshcipher_ctx *cc)
  * passphrase and using the resulting 16 bytes as the key.
  */
 int
-cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
-    const char *passphrase, int do_encrypt)
+cipher_set_key_string(struct sshcipher_ctx **ccp,
+    const struct sshcipher *cipher, const char *passphrase, int do_encrypt)
 {
        u_char digest[16];
        int r = SSH_ERR_INTERNAL_ERROR;
@@ -484,7 +537,7 @@ cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
            digest, sizeof(digest))) != 0)
                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:
        explicit_bzero(digest, sizeof(digest));
        return r;
@@ -509,7 +562,7 @@ cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
                ivlen = sizeof(cc->ac_ctx.ctr);
 #ifdef WITH_OPENSSL
        else
-               ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+               ivlen = EVP_CIPHER_CTX_iv_length(cc->evp);
 #endif /* WITH_OPENSSL */
        return (ivlen);
 }
@@ -541,7 +594,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
        case SSH_CIPHER_SSH2:
        case SSH_CIPHER_DES:
        case SSH_CIPHER_BLOWFISH:
-               evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+               evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
                if (evplen == 0)
                        return 0;
                else if (evplen < 0)
@@ -549,16 +602,16 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
                if ((u_int)evplen != len)
                        return SSH_ERR_INVALID_ARGUMENT;
                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))
                               return SSH_ERR_LIBCRYPTO_ERROR;
                } else
-                       memcpy(iv, cc->evp.iv, len);
+                       memcpy(iv, cc->evp->iv, len);
                break;
 #endif
 #ifdef WITH_SSH1
        case SSH_CIPHER_3DES:
-               return ssh1_3des_iv(&cc->evp, 0, iv, 24);
+               return ssh1_3des_iv(cc->evp, 0, iv, 24);
 #endif
        default:
                return SSH_ERR_INVALID_ARGUMENT;
@@ -584,21 +637,21 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
        case SSH_CIPHER_SSH2:
        case SSH_CIPHER_DES:
        case SSH_CIPHER_BLOWFISH:
-               evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+               evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
                if (evplen <= 0)
                        return SSH_ERR_LIBCRYPTO_ERROR;
                if (cipher_authlen(c)) {
                        /* 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))
                                return SSH_ERR_LIBCRYPTO_ERROR;
                } else
-                       memcpy(cc->evp.iv, iv, evplen);
+                       memcpy(cc->evp->iv, iv, evplen);
                break;
 #endif
 #ifdef WITH_SSH1
        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
        default:
                return SSH_ERR_INVALID_ARGUMENT;
@@ -607,8 +660,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
 }
 
 #ifdef WITH_OPENSSL
-#define EVP_X_STATE(evp)       (evp).cipher_data
-#define EVP_X_STATE_LEN(evp)   (evp).cipher->ctx_size
+#define EVP_X_STATE(evp)       (evp)->cipher_data
+#define EVP_X_STATE_LEN(evp)   (evp)->cipher->ctx_size
 #endif
 
 int
index 06d4be4..f4bca62 100644 (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>
 #define CIPHER_DECRYPT         0
 
 struct sshcipher;
-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_ctx;
 
 u_int   cipher_mask_ssh1(int);
 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 *);
 int     ciphers_valid(const char *);
 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);
 int     cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
     u_int, u_int, u_int);
 int     cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
     const u_char *, u_int);
-int     cipher_cleanup(struct sshcipher_ctx *);
-int     cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *,
-    const char *, int);
+void    cipher_free(struct sshcipher_ctx *);
+int     cipher_set_key_string(struct sshcipher_ctx **,
+    const struct sshcipher *, const char *, int);
 u_int   cipher_blocksize(const struct sshcipher *);
 u_int   cipher_keylen(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_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 *);
 int     cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
 int     cipher_set_keyiv(struct sshcipher_ctx *, const 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 *, const u_char *);
+
 #endif                         /* CIPHER_H */
index d3914a7..ff7a0e5 100644 (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>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -116,10 +116,10 @@ struct session_state {
        u_int remote_protocol_flags;
 
        /* 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. */
-       struct sshcipher_ctx send_context;
+       struct sshcipher_ctx *send_context;
 
        /* Buffer for raw input data from the socket. */
        struct sshbuf *input;
@@ -518,7 +518,6 @@ void
 ssh_packet_close(struct ssh *ssh)
 {
        struct session_state *state = ssh->state;
-       int r;
        u_int mode;
 
        if (!state->initialized)
@@ -562,10 +561,9 @@ ssh_packet_close(struct ssh *ssh)
                                inflateEnd(stream);
                }
        }
-       if ((r = cipher_cleanup(&state->send_context)) != 0)
-               error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
-       if ((r = cipher_cleanup(&state->receive_context)) != 0)
-               error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
+       cipher_free(state->send_context);
+       cipher_free(state->receive_context);
+       state->send_context = state->receive_context = NULL;
        free(ssh->remote_ipaddr);
        ssh->remote_ipaddr = NULL;
        free(ssh->state);
@@ -859,8 +857,8 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen,
            NULL, 0, CIPHER_DECRYPT) != 0))
                fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
        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);
                state->cipher_warning_done = 1;
        }
@@ -906,7 +904,7 @@ ssh_packet_send1(struct ssh *ssh)
 
        /* Insert padding. Initialized to zero in packet_start1() */
        padding = 8 - len % 8;
-       if (!state->send_context.plaintext) {
+       if (!cipher_ctx_is_plaintext(state->send_context)) {
                cp = sshbuf_mutable_ptr(state->outgoing_packet);
                if (cp == NULL) {
                        r = SSH_ERR_INTERNAL_ERROR;
@@ -936,7 +934,7 @@ ssh_packet_send1(struct ssh *ssh)
        if ((r = sshbuf_reserve(state->output,
            sshbuf_len(state->outgoing_packet), &cp)) != 0)
                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_len(state->outgoing_packet), 0, 0)) != 0)
                goto out;
@@ -967,7 +965,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
        struct sshenc *enc;
        struct sshmac *mac;
        struct sshcomp *comp;
-       struct sshcipher_ctx *cc;
+       struct sshcipher_ctx **ccp;
        u_int64_t *max_blocks;
        const char *wmsg;
        int r, crypt_type;
@@ -975,12 +973,12 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
        debug2("set_newkeys: mode %d", mode);
 
        if (mode == MODE_OUT) {
-               cc = &state->send_context;
+               ccp = &state->send_context;
                crypt_type = CIPHER_ENCRYPT;
                state->p_send.packets = state->p_send.blocks = 0;
                max_blocks = &state->max_blocks_out;
        } else {
-               cc = &state->receive_context;
+               ccp = &state->receive_context;
                crypt_type = CIPHER_DECRYPT;
                state->p_read.packets = state->p_read.blocks = 0;
                max_blocks = &state->max_blocks_in;
@@ -992,8 +990,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
                   (unsigned long long)state->p_read.blocks,
                   (unsigned long long)state->p_send.bytes,
                   (unsigned long long)state->p_send.blocks);
-               if ((r = cipher_cleanup(cc)) != 0)
-                       return r;
+               cipher_free(*ccp);
+               *ccp = NULL;
                enc  = &state->newkeys[mode]->enc;
                mac  = &state->newkeys[mode]->mac;
                comp = &state->newkeys[mode]->comp;
@@ -1022,11 +1020,11 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
        }
        mac->enabled = 1;
        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)
                return r;
        if (!state->cipher_warning_done &&
-           (wmsg = cipher_warning_message(cc)) != NULL) {
+           (wmsg = cipher_warning_message(*ccp)) != NULL) {
                error("Warning: %s", wmsg);
                state->cipher_warning_done = 1;
        }
@@ -1248,7 +1246,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
        }
        if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
                goto out;
-       if (enc && !state->send_context.plaintext) {
+       if (enc && !cipher_ctx_is_plaintext(state->send_context)) {
                /* random padding */
                arc4random_buf(cp, padlen);
        } else {
@@ -1280,7 +1278,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
        if ((r = sshbuf_reserve(state->output,
            sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
                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),
            len - aadlen, aadlen, authlen)) != 0)
                goto out;
@@ -1594,7 +1592,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
         * (C)1998 CORE-SDI, Buenos Aires Argentina
         * Ariel Futoransky(futo@core-sdi.com)
         */
-       if (!state->receive_context.plaintext) {
+       if (!cipher_ctx_is_plaintext(state->receive_context)) {
                emsg = NULL;
                switch (detect_attack(&state->deattack,
                    sshbuf_ptr(state->input), padded_len)) {
@@ -1623,7 +1621,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
        sshbuf_reset(state->incoming_packet);
        if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0)
                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)
                goto out;
 
@@ -1721,7 +1719,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;
 
        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,
                    sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
                        return 0;
@@ -1747,7 +1745,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,
                    &cp)) != 0)
                        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),
                    block_size, 0, 0)) != 0)
                        goto out;
@@ -1815,7 +1813,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,
            &cp)) != 0)
                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)
                goto out;
        if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
@@ -2489,8 +2487,8 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
        enc = &newkey->enc;
        mac = &newkey->mac;
        comp = &newkey->comp;
-       cc = (mode == MODE_OUT) ? &ssh->state->send_context :
-           &ssh->state->receive_context;
+       cc = (mode == MODE_OUT) ? ssh->state->send_context :
+           ssh->state->receive_context;
        if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
                return r;
        if ((b = sshbuf_new()) == NULL)
@@ -2529,18 +2527,18 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
        int r, ssh1cipher;
 
        if (!compat20) {
-               ssh1cipher = cipher_get_number(state->receive_context.cipher);
-               slen = cipher_get_keyiv_len(&state->send_context);
-               rlen = cipher_get_keyiv_len(&state->receive_context);
+               ssh1cipher = cipher_ctx_get_number(state->receive_context);
+               slen = cipher_get_keyiv_len(state->send_context);
+               rlen = cipher_get_keyiv_len(state->receive_context);
                if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
                    (r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
                    (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
                    (r = sshbuf_put_u32(m, slen)) != 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_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;
        } else {
                if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
@@ -2559,17 +2557,17 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
                        return r;
        }
 
-       slen = cipher_get_keycontext(&state->send_context, NULL);
-       rlen = cipher_get_keycontext(&state->receive_context, NULL);
+       slen = cipher_get_keycontext(state->send_context, NULL);
+       rlen = cipher_get_keycontext(state->receive_context, NULL);
        if ((r = sshbuf_put_u32(m, slen)) != 0 ||
            (r = sshbuf_reserve(m, slen, &p)) != 0)
                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;
        if ((r = sshbuf_put_u32(m, rlen)) != 0 ||
            (r = sshbuf_reserve(m, rlen, &p)) != 0)
                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;
 
        if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 ||
@@ -2715,11 +2713,11 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
                        return SSH_ERR_KEY_UNKNOWN_CIPHER;
                ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
                    (int)ssh1cipher);
-               if (cipher_get_keyiv_len(&state->send_context) != (int)slen ||
-                   cipher_get_keyiv_len(&state->receive_context) != (int)rlen)
+               if (cipher_get_keyiv_len(state->send_context) != (int)slen ||
+                   cipher_get_keyiv_len(state->receive_context) != (int)rlen)
                        return SSH_ERR_INVALID_FORMAT;
-               if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 ||
-                   (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0)
+               if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 ||
+                   (r = cipher_set_keyiv(state->receive_context, ivin)) != 0)
                        return r;
        } else {
                if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
@@ -2749,11 +2747,11 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
        if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
            (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
                return r;
-       if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen ||
-           cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen)
+       if (cipher_get_keycontext(state->send_context, NULL) != (int)slen ||
+           cipher_get_keycontext(state->receive_context, NULL) != (int)rlen)
                return SSH_ERR_INVALID_FORMAT;
-       cipher_set_keycontext(&state->send_context, keyout);
-       cipher_set_keycontext(&state->receive_context, keyin);
+       cipher_set_keycontext(state->send_context, keyout);
+       cipher_set_keycontext(state->receive_context, keyin);
 
        if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 ||
            (r = ssh_packet_set_postauth(ssh)) != 0)
index 2c97cf2..f570afb 100644 (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) 2008 Alexander von Gernler.  All rights reserved.
@@ -2979,13 +2979,11 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
        size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
        u_int check;
        int r = SSH_ERR_INTERNAL_ERROR;
-       struct sshcipher_ctx ciphercontext;
+       struct sshcipher_ctx *ciphercontext = NULL;
        const struct sshcipher *cipher;
        const char *kdfname = KDFNAME;
        struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
 
-       memset(&ciphercontext, 0, sizeof(ciphercontext));
-
        if (rounds <= 0)
                rounds = DEFAULT_ROUNDS;
        if (passphrase == NULL || !strlen(passphrase)) {
@@ -3072,7 +3070,7 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
        if ((r = sshbuf_reserve(encoded,
            sshbuf_len(encrypted) + authlen, &cp)) != 0)
                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)
                goto out;
 
@@ -3104,7 +3102,7 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
        sshbuf_free(kdf);
        sshbuf_free(encoded);
        sshbuf_free(encrypted);
-       cipher_cleanup(&ciphercontext);
+       cipher_free(ciphercontext);
        explicit_bzero(salt, sizeof(salt));
        if (key != NULL) {
                explicit_bzero(key, keylen + ivlen);
@@ -3133,12 +3131,11 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
        size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
        struct sshbuf *encoded = NULL, *decoded = NULL;
        struct sshbuf *kdf = NULL, *decrypted = NULL;
-       struct sshcipher_ctx ciphercontext;
+       struct sshcipher_ctx *ciphercontext = NULL;
        struct sshkey *k = NULL;
        u_char *key = NULL, *salt = NULL, *dp, pad, last;
        u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
 
-       memset(&ciphercontext, 0, sizeof(ciphercontext));
        if (keyp != NULL)
                *keyp = NULL;
        if (commentp != NULL)
@@ -3267,7 +3264,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
            (r = cipher_init(&ciphercontext, cipher, key, keylen,
            key + keylen, ivlen, 0)) != 0)
                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) {
                /* an integrity error here indicates an incorrect passphrase */
                if (r == SSH_ERR_MAC_INVALID)
@@ -3321,7 +3318,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
        }
  out:
        pad = 0;
-       cipher_cleanup(&ciphercontext);
+       cipher_free(ciphercontext);
        free(ciphername);
        free(kdfname);
        free(comment);
@@ -3355,7 +3352,7 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
        struct sshbuf *buffer = NULL, *encrypted = NULL;
        u_char buf[8];
        int r, cipher_num;
-       struct sshcipher_ctx ciphercontext;
+       struct sshcipher_ctx *ciphercontext = NULL;
        const struct sshcipher *cipher;
        u_char *cp;
 
@@ -3425,16 +3422,14 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
        if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
            CIPHER_ENCRYPT)) != 0)
                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)
                goto out;
-       if ((r = cipher_cleanup(&ciphercontext)) != 0)
-               goto out;
 
        r = sshbuf_putb(blob, encrypted);
 
  out:
-       explicit_bzero(&ciphercontext, sizeof(ciphercontext));
+       cipher_free(ciphercontext);
        explicit_bzero(buf, sizeof(buf));
        sshbuf_free(buffer);
        sshbuf_free(encrypted);
@@ -3598,7 +3593,7 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
        struct sshbuf *decrypted = NULL, *copy = NULL;
        u_char *cp;
        char *comment = NULL;
-       struct sshcipher_ctx ciphercontext;
+       struct sshcipher_ctx *ciphercontext = NULL;
        const struct sshcipher *cipher;
        struct sshkey *prv = NULL;
 
@@ -3656,12 +3651,8 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
        if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
            CIPHER_DECRYPT)) != 0)
                goto out;
-       if ((r = cipher_crypt(&ciphercontext, 0, cp,
-           sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) {
-               cipher_cleanup(&ciphercontext);
-               goto out;
-       }
-       if ((r = cipher_cleanup(&ciphercontext)) != 0)
+       if ((r = cipher_crypt(ciphercontext, 0, cp,
+           sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0)
                goto out;
 
        if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
@@ -3698,7 +3689,7 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
                comment = NULL;
        }
  out:
-       explicit_bzero(&ciphercontext, sizeof(ciphercontext));
+       cipher_free(ciphercontext);
        free(comment);
        sshkey_free(prv);
        sshbuf_free(copy);