Blame src/wrapper.c

Packit Service 31306d
/*
Packit Service 31306d
 * wrapper.c - wrapper for crytpo functions
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2003-2013   by Aris Adamantiadis
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
/*
Packit Service 31306d
 * Why a wrapper?
Packit Service 31306d
 *
Packit Service 31306d
 * Let's say you want to port libssh from libcrypto of openssl to libfoo
Packit Service 31306d
 * you are going to spend hours to remove every references to SHA1_Update()
Packit Service 31306d
 * to libfoo_sha1_update after the work is finished, you're going to have
Packit Service 31306d
 * only this file to modify it's not needed to say that your modifications
Packit Service 31306d
 * are welcome.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
Packit Service 31306d
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
#include <string.h>
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_ZLIB
Packit Service 31306d
#include <zlib.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
#include "libssh/session.h"
Packit Service 31306d
#include "libssh/crypto.h"
Packit Service 31306d
#include "libssh/wrapper.h"
Packit Service 31306d
#include "libssh/pki.h"
Packit Service 31306d
#include "libssh/poly1305.h"
Packit Service 31306d
#include "libssh/dh.h"
Packit Service 31306d
#ifdef WITH_GEX
Packit Service 31306d
#include "libssh/dh-gex.h"
Packit Service 31306d
#endif /* WITH_GEX */
Packit Service 31306d
#include "libssh/ecdh.h"
Packit Service 31306d
#include "libssh/curve25519.h"
Packit Service 31306d
Packit Service 31306d
static struct ssh_hmac_struct ssh_hmac_tab[] = {
Packit Service 31306d
  { "hmac-sha1",                     SSH_HMAC_SHA1,          false },
Packit Service 31306d
  { "hmac-sha2-256",                 SSH_HMAC_SHA256,        false },
Packit Service 31306d
  { "hmac-sha2-512",                 SSH_HMAC_SHA512,        false },
Packit Service 31306d
  { "hmac-md5",                      SSH_HMAC_MD5,           false },
Packit Service 31306d
  { "aead-poly1305",                 SSH_HMAC_AEAD_POLY1305, false },
Packit Service 31306d
  { "aead-gcm",                      SSH_HMAC_AEAD_GCM,      false },
Packit Service 31306d
  { "hmac-sha1-etm@openssh.com",     SSH_HMAC_SHA1,          true  },
Packit Service 31306d
  { "hmac-sha2-256-etm@openssh.com", SSH_HMAC_SHA256,        true  },
Packit Service 31306d
  { "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512,        true  },
Packit Service 31306d
  { "hmac-md5-etm@openssh.com",      SSH_HMAC_MD5,           true  },
Packit Service 31306d
  { NULL,                            0,                      false }
Packit Service 31306d
};
Packit Service 31306d
Packit Service 31306d
struct ssh_hmac_struct *ssh_get_hmactab(void) {
Packit Service 31306d
  return ssh_hmac_tab;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
size_t hmac_digest_len(enum ssh_hmac_e type) {
Packit Service 31306d
  switch(type) {
Packit Service 31306d
    case SSH_HMAC_SHA1:
Packit Service 31306d
      return SHA_DIGEST_LEN;
Packit Service 31306d
    case SSH_HMAC_SHA256:
Packit Service 31306d
      return SHA256_DIGEST_LEN;
Packit Service 31306d
    case SSH_HMAC_SHA512:
Packit Service 31306d
      return SHA512_DIGEST_LEN;
Packit Service 31306d
    case SSH_HMAC_MD5:
Packit Service 31306d
      return MD5_DIGEST_LEN;
Packit Service 31306d
    case SSH_HMAC_AEAD_POLY1305:
Packit Service 31306d
      return POLY1305_TAGLEN;
Packit Service 31306d
    case SSH_HMAC_AEAD_GCM:
Packit Service 31306d
      return AES_GCM_TAGLEN;
Packit Service 31306d
    default:
Packit Service 31306d
      return 0;
Packit Service 31306d
  }
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm)
Packit Service 31306d
{
Packit Service 31306d
  int i = 0;
Packit Service 31306d
  struct ssh_hmac_struct *ssh_hmactab = ssh_get_hmactab();
Packit Service 31306d
  while (ssh_hmactab[i].name &&
Packit Service 31306d
         ((ssh_hmactab[i].hmac_type != hmac_type) ||
Packit Service 31306d
          (ssh_hmactab[i].etm != etm))) {
Packit Service 31306d
    i++;
Packit Service 31306d
  }
Packit Service 31306d
  return ssh_hmactab[i].name;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/* it allocates a new cipher structure based on its offset into the global table */
Packit Service 31306d
static struct ssh_cipher_struct *cipher_new(int offset) {
Packit Service 31306d
  struct ssh_cipher_struct *cipher = NULL;
Packit Service 31306d
Packit Service 31306d
  cipher = malloc(sizeof(struct ssh_cipher_struct));
Packit Service 31306d
  if (cipher == NULL) {
Packit Service 31306d
    return NULL;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  /* note the memcpy will copy the pointers : so, you shouldn't free them */
Packit Service 31306d
  memcpy(cipher, &ssh_get_ciphertab()[offset], sizeof(*cipher));
Packit Service 31306d
Packit Service 31306d
  return cipher;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
void ssh_cipher_clear(struct ssh_cipher_struct *cipher){
Packit Service 31306d
#ifdef HAVE_LIBGCRYPT
Packit Service 31306d
    unsigned int i;
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    if (cipher == NULL) {
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_LIBGCRYPT
Packit Service 31306d
    if (cipher->key) {
Packit Service 31306d
        for (i = 0; i < (cipher->keylen / sizeof(gcry_cipher_hd_t)); i++) {
Packit Service 31306d
            gcry_cipher_close(cipher->key[i]);
Packit Service 31306d
        }
Packit Service 31306d
        SAFE_FREE(cipher->key);
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    if (cipher->cleanup != NULL) {
Packit Service 31306d
        cipher->cleanup(cipher);
Packit Service 31306d
    }
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static void cipher_free(struct ssh_cipher_struct *cipher) {
Packit Service 31306d
  ssh_cipher_clear(cipher);
Packit Service 31306d
  SAFE_FREE(cipher);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
struct ssh_crypto_struct *crypto_new(void) {
Packit Service 31306d
   struct ssh_crypto_struct *crypto;
Packit Service 31306d
Packit Service 31306d
  crypto = malloc(sizeof(struct ssh_crypto_struct));
Packit Service 31306d
  if (crypto == NULL) {
Packit Service 31306d
    return NULL;
Packit Service 31306d
  }
Packit Service 31306d
  ZERO_STRUCTP(crypto);
Packit Service 31306d
  return crypto;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
void crypto_free(struct ssh_crypto_struct *crypto)
Packit Service 31306d
{
Packit Service 31306d
    size_t i;
Packit Service 31306d
Packit Service 31306d
    if (crypto == NULL) {
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_key_free(crypto->server_pubkey);
Packit Service 31306d
Packit Service 31306d
    ssh_dh_cleanup(crypto);
Packit Service 31306d
    bignum_safe_free(crypto->shared_secret);
Packit Service 31306d
#ifdef HAVE_ECDH
Packit Service 31306d
    SAFE_FREE(crypto->ecdh_client_pubkey);
Packit Service 31306d
    SAFE_FREE(crypto->ecdh_server_pubkey);
Packit Service 31306d
    if(crypto->ecdh_privkey != NULL){
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
        EC_KEY_free(crypto->ecdh_privkey);
Packit Service 31306d
#elif defined HAVE_GCRYPT_ECC
Packit Service 31306d
        gcry_sexp_release(crypto->ecdh_privkey);
Packit Service 31306d
#endif
Packit Service 31306d
        crypto->ecdh_privkey = NULL;
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
    if (crypto->session_id != NULL) {
Packit Service 31306d
        explicit_bzero(crypto->session_id, crypto->digest_len);
Packit Service 31306d
        SAFE_FREE(crypto->session_id);
Packit Service 31306d
    }
Packit Service 31306d
    if (crypto->secret_hash != NULL) {
Packit Service 31306d
        explicit_bzero(crypto->secret_hash, crypto->digest_len);
Packit Service 31306d
        SAFE_FREE(crypto->secret_hash);
Packit Service 31306d
    }
Packit Service 31306d
#ifdef WITH_ZLIB
Packit Service 31306d
    if (crypto->compress_out_ctx &&
Packit Service 31306d
        (deflateEnd(crypto->compress_out_ctx) != 0)) {
Packit Service 31306d
        inflateEnd(crypto->compress_out_ctx);
Packit Service 31306d
    }
Packit Service 31306d
    SAFE_FREE(crypto->compress_out_ctx);
Packit Service 31306d
Packit Service 31306d
    if (crypto->compress_in_ctx &&
Packit Service 31306d
        (deflateEnd(crypto->compress_in_ctx) != 0)) {
Packit Service 31306d
        inflateEnd(crypto->compress_in_ctx);
Packit Service 31306d
    }
Packit Service 31306d
    SAFE_FREE(crypto->compress_in_ctx);
Packit Service 31306d
#endif /* WITH_ZLIB */
Packit Service 31306d
    SAFE_FREE(crypto->encryptIV);
Packit Service 31306d
    SAFE_FREE(crypto->decryptIV);
Packit Service 31306d
    SAFE_FREE(crypto->encryptMAC);
Packit Service 31306d
    SAFE_FREE(crypto->decryptMAC);
Packit Service 31306d
    if (crypto->encryptkey != NULL) {
Packit Service 31306d
        explicit_bzero(crypto->encryptkey, crypto->out_cipher->keysize / 8);
Packit Service 31306d
        SAFE_FREE(crypto->encryptkey);
Packit Service 31306d
    }
Packit Service 31306d
    if (crypto->decryptkey != NULL) {
Packit Service 31306d
        explicit_bzero(crypto->decryptkey, crypto->in_cipher->keysize / 8);
Packit Service 31306d
        SAFE_FREE(crypto->decryptkey);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    cipher_free(crypto->in_cipher);
Packit Service 31306d
    cipher_free(crypto->out_cipher);
Packit Service 31306d
Packit Service 31306d
    for (i = 0; i < SSH_KEX_METHODS; i++) {
Packit Service 31306d
        SAFE_FREE(crypto->client_kex.methods[i]);
Packit Service 31306d
        SAFE_FREE(crypto->server_kex.methods[i]);
Packit Service 31306d
        SAFE_FREE(crypto->kex_methods[i]);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    explicit_bzero(crypto, sizeof(struct ssh_crypto_struct));
Packit Service 31306d
Packit Service 31306d
    SAFE_FREE(crypto);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int crypt_set_algorithms2(ssh_session session)
Packit Service 31306d
{
Packit Service 31306d
    const char *wanted = NULL;
Packit Service 31306d
    struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
Packit Service 31306d
    struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
Packit Service 31306d
    size_t i = 0;
Packit Service 31306d
    int cmp;
Packit Service 31306d
Packit Service 31306d
    /*
Packit Service 31306d
     * We must scan the kex entries to find crypto algorithms and set their
Packit Service 31306d
     * appropriate structure.
Packit Service 31306d
     */
Packit Service 31306d
Packit Service 31306d
    /* out */
Packit Service 31306d
    wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
Packit Service 31306d
    for (i = 0; i < 64 && ssh_ciphertab[i].name != NULL; ++i) {
Packit Service 31306d
        cmp = strcmp(wanted, ssh_ciphertab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_ciphertab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
                "crypt_set_algorithms2: no crypto algorithm function found for %s",
Packit Service 31306d
                wanted);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set output algorithm to %s", wanted);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->out_cipher = cipher_new(i);
Packit Service 31306d
    if (session->next_crypto->out_cipher == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->next_crypto->out_cipher->aead_encrypt != NULL) {
Packit Service 31306d
        /* this cipher has integrated MAC */
Packit Service 31306d
        if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
Packit Service 31306d
            wanted = "aead-poly1305";
Packit Service 31306d
        } else {
Packit Service 31306d
            wanted = "aead-gcm";
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        /*
Packit Service 31306d
         * We must scan the kex entries to find hmac algorithms and set their
Packit Service 31306d
         * appropriate structure.
Packit Service 31306d
         */
Packit Service 31306d
Packit Service 31306d
        /* out */
Packit Service 31306d
        wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(wanted, ssh_hmactab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_hmactab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
                "crypt_set_algorithms2: no hmac algorithm function found for %s",
Packit Service 31306d
                wanted);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
Packit Service 31306d
    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
Packit Service 31306d
Packit Service 31306d
    /* in */
Packit Service 31306d
    wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(wanted, ssh_ciphertab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_ciphertab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
                "Crypt_set_algorithms: no crypto algorithm function found for %s",
Packit Service 31306d
                wanted);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set input algorithm to %s", wanted);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->in_cipher = cipher_new(i);
Packit Service 31306d
    if (session->next_crypto->in_cipher == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->next_crypto->in_cipher->aead_encrypt != NULL){
Packit Service 31306d
        /* this cipher has integrated MAC */
Packit Service 31306d
        if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
Packit Service 31306d
            wanted = "aead-poly1305";
Packit Service 31306d
        } else {
Packit Service 31306d
            wanted = "aead-gcm";
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
Packit Service 31306d
        wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(wanted, ssh_hmactab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_hmactab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
                "crypt_set_algorithms2: no hmac algorithm function found for %s",
Packit Service 31306d
                wanted);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
Packit Service 31306d
    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
Packit Service 31306d
Packit Service 31306d
    /* compression */
Packit Service 31306d
    cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib");
Packit Service 31306d
    if (cmp == 0) {
Packit Service 31306d
        session->next_crypto->do_compress_out = 1;
Packit Service 31306d
    }
Packit Service 31306d
    cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib");
Packit Service 31306d
    if (cmp == 0) {
Packit Service 31306d
        session->next_crypto->do_compress_in = 1;
Packit Service 31306d
    }
Packit Service 31306d
    cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib@openssh.com");
Packit Service 31306d
    if (cmp == 0) {
Packit Service 31306d
        session->next_crypto->delayed_compress_out = 1;
Packit Service 31306d
    }
Packit Service 31306d
    cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib@openssh.com");
Packit Service 31306d
    if (cmp == 0) {
Packit Service 31306d
        session->next_crypto->delayed_compress_in = 1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int crypt_set_algorithms_client(ssh_session session)
Packit Service 31306d
{
Packit Service 31306d
    return crypt_set_algorithms2(session);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
int crypt_set_algorithms_server(ssh_session session){
Packit Service 31306d
    const char *method = NULL;
Packit Service 31306d
    size_t i = 0;
Packit Service 31306d
    struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
Packit Service 31306d
    struct ssh_hmac_struct   *ssh_hmactab=ssh_get_hmactab();
Packit Service 31306d
    int cmp;
Packit Service 31306d
Packit Service 31306d
Packit Service 31306d
    if (session == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /*
Packit Service 31306d
     * We must scan the kex entries to find crypto algorithms and set their
Packit Service 31306d
     * appropriate structure
Packit Service 31306d
     */
Packit Service 31306d
    /* out */
Packit Service 31306d
    method = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(method, ssh_ciphertab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
          break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_ciphertab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session,SSH_FATAL,"crypt_set_algorithms_server : "
Packit Service 31306d
                "no crypto algorithm function found for %s",method);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET,"Set output algorithm %s",method);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->out_cipher = cipher_new(i);
Packit Service 31306d
    if (session->next_crypto->out_cipher == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->next_crypto->out_cipher->aead_encrypt != NULL){
Packit Service 31306d
        /* this cipher has integrated MAC */
Packit Service 31306d
        if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
Packit Service 31306d
            method = "aead-poly1305";
Packit Service 31306d
        } else {
Packit Service 31306d
            method = "aead-gcm";
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
Packit Service 31306d
        /* out */
Packit Service 31306d
        method = session->next_crypto->kex_methods[SSH_MAC_S_C];
Packit Service 31306d
    }
Packit Service 31306d
    /* HMAC algorithm selection */
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(method, ssh_hmactab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_hmactab[i].name == NULL) {
Packit Service 31306d
      ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
          "crypt_set_algorithms_server: no hmac algorithm function found for %s",
Packit Service 31306d
          method);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", method);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
Packit Service 31306d
    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
Packit Service 31306d
Packit Service 31306d
    /* in */
Packit Service 31306d
    method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_ciphertab[i].name; i++) {
Packit Service 31306d
        cmp = strcmp(method, ssh_ciphertab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_ciphertab[i].name == NULL) {
Packit Service 31306d
        ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server :"
Packit Service 31306d
                "no crypto algorithm function found for %s",method);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET,"Set input algorithm %s",method);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->in_cipher = cipher_new(i);
Packit Service 31306d
    if (session->next_crypto->in_cipher == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->next_crypto->in_cipher->aead_encrypt != NULL){
Packit Service 31306d
        /* this cipher has integrated MAC */
Packit Service 31306d
        if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) {
Packit Service 31306d
            method = "aead-poly1305";
Packit Service 31306d
        } else {
Packit Service 31306d
            method = "aead-gcm";
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
Packit Service 31306d
        method = session->next_crypto->kex_methods[SSH_MAC_C_S];
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
Packit Service 31306d
        cmp = strcmp(method, ssh_hmactab[i].name);
Packit Service 31306d
        if (cmp == 0) {
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (ssh_hmactab[i].name == NULL) {
Packit Service 31306d
      ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
          "crypt_set_algorithms_server: no hmac algorithm function found for %s",
Packit Service 31306d
          method);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method);
Packit Service 31306d
Packit Service 31306d
    session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
Packit Service 31306d
    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
Packit Service 31306d
Packit Service 31306d
    /* compression */
Packit Service 31306d
    method = session->next_crypto->kex_methods[SSH_COMP_C_S];
Packit Service 31306d
    if(strcmp(method,"zlib") == 0){
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET,"enabling C->S compression");
Packit Service 31306d
        session->next_crypto->do_compress_in=1;
Packit Service 31306d
    }
Packit Service 31306d
    if(strcmp(method,"zlib@openssh.com") == 0){
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET,"enabling C->S delayed compression");
Packit Service 31306d
Packit Service 31306d
        if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
Packit Service 31306d
            session->next_crypto->do_compress_in = 1;
Packit Service 31306d
        } else {
Packit Service 31306d
            session->next_crypto->delayed_compress_in = 1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    method = session->next_crypto->kex_methods[SSH_COMP_S_C];
Packit Service 31306d
    if(strcmp(method,"zlib") == 0){
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression");
Packit Service 31306d
        session->next_crypto->do_compress_out=1;
Packit Service 31306d
    }
Packit Service 31306d
    if(strcmp(method,"zlib@openssh.com") == 0){
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression");
Packit Service 31306d
Packit Service 31306d
        if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
Packit Service 31306d
            session->next_crypto->do_compress_out = 1;
Packit Service 31306d
        } else {
Packit Service 31306d
            session->next_crypto->delayed_compress_out = 1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
Packit Service 31306d
    session->srv.hostkey = ssh_key_type_from_signature_name(method);
Packit Service 31306d
    session->srv.hostkey_digest = ssh_key_hash_from_name(method);
Packit Service 31306d
Packit Service 31306d
    /* setup DH key exchange type */
Packit Service 31306d
    switch (session->next_crypto->kex_type) {
Packit Service 31306d
    case SSH_KEX_DH_GROUP1_SHA1:
Packit Service 31306d
    case SSH_KEX_DH_GROUP14_SHA1:
Packit Service 31306d
    case SSH_KEX_DH_GROUP14_SHA256:
Packit Service 31306d
    case SSH_KEX_DH_GROUP16_SHA512:
Packit Service 31306d
    case SSH_KEX_DH_GROUP18_SHA512:
Packit Service 31306d
      ssh_server_dh_init(session);
Packit Service 31306d
      break;
Packit Service 31306d
#ifdef WITH_GEX
Packit Service 31306d
    case SSH_KEX_DH_GEX_SHA1:
Packit Service 31306d
    case SSH_KEX_DH_GEX_SHA256:
Packit Service 31306d
      ssh_server_dhgex_init(session);
Packit Service 31306d
      break;
Packit Service 31306d
#endif /* WITH_GEX */
Packit Service 31306d
#ifdef HAVE_ECDH
Packit Service 31306d
    case SSH_KEX_ECDH_SHA2_NISTP256:
Packit Service 31306d
    case SSH_KEX_ECDH_SHA2_NISTP384:
Packit Service 31306d
    case SSH_KEX_ECDH_SHA2_NISTP521:
Packit Service 31306d
      ssh_server_ecdh_init(session);
Packit Service 31306d
      break;
Packit Service 31306d
#endif
Packit Service 31306d
#ifdef HAVE_CURVE25519
Packit Service 31306d
    case SSH_KEX_CURVE25519_SHA256:
Packit Service 31306d
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
Packit Service 31306d
        ssh_server_curve25519_init(session);
Packit Service 31306d
        break;
Packit Service 31306d
#endif
Packit Service 31306d
    default:
Packit Service 31306d
        ssh_set_error(session,
Packit Service 31306d
                      SSH_FATAL,
Packit Service 31306d
                      "crypt_set_algorithms_server: could not find init "
Packit Service 31306d
                      "handler for kex type %d",
Packit Service 31306d
                      session->next_crypto->kex_type);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif /* WITH_SERVER */