From 32a036ab72850c918d7aa521e7844be59c6a3b4a Mon Sep 17 00:00:00 2001 From: djm Date: Wed, 3 Aug 2016 05:41:57 +0000 Subject: [PATCH] small refactor of cipher.c: make ciphercontext opaque to callers feedback and ok markus@ --- usr.bin/ssh/cipher-chachapoly.c | 5 +- usr.bin/ssh/cipher.c | 165 +++++++++++++++++++++----------- usr.bin/ssh/cipher.h | 23 ++--- usr.bin/ssh/packet.c | 88 +++++++++-------- usr.bin/ssh/sshkey.c | 37 +++---- 5 files changed, 179 insertions(+), 139 deletions(-) diff --git a/usr.bin/ssh/cipher-chachapoly.c b/usr.bin/ssh/cipher-chachapoly.c index 5f5d9165ebd..e5746dd4685 100644 --- a/usr.bin/ssh/cipher-chachapoly.c +++ b/usr.bin/ssh/cipher-chachapoly.c @@ -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 #include /* 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 */ diff --git a/usr.bin/ssh/cipher.c b/usr.bin/ssh/cipher.c index c4341e270db..b4916a49ebf 100644 --- a/usr.bin/ssh/cipher.c +++ b/usr.bin/ssh/cipher.c @@ -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 * Copyright (c) 1995 Tatu Ylonen , 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 diff --git a/usr.bin/ssh/cipher.h b/usr.bin/ssh/cipher.h index 06d4be4d75e..f4bca6285fa 100644 --- a/usr.bin/ssh/cipher.h +++ b/usr.bin/ssh/cipher.h @@ -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 @@ -63,14 +63,7 @@ #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 */ diff --git a/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c index d3914a7c48d..ff7a0e57631 100644 --- a/usr.bin/ssh/packet.c +++ b/usr.bin/ssh/packet.c @@ -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 * Copyright (c) 1995 Tatu Ylonen , 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) diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index 2c97cf23499..f570afb8b3e 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -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); -- 2.20.1