Exemple #1
0
static int dh_handshake_server(ssh_session session) {
  ssh_key privkey;
  ssh_string sig_blob;
  ssh_string f;
  int rc;

  if (dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  if (ssh_get_key_params(session,&privkey) != SSH_OK){
      ssh_string_free(f);
      return -1;
  }

  if (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    ssh_string_free(f);
    return -1;
  }

  if (make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    ssh_string_free(f);
    return -1;
  }

  sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
  if (sig_blob == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    ssh_string_free(f);
    return -1;
  }

  rc = ssh_buffer_pack(session->out_buffer,
                       "bSSS",
                       SSH2_MSG_KEXDH_REPLY,
                       session->next_crypto->server_pubkey,
                       f,
                       sig_blob);
  ssh_string_free(f);
  ssh_string_free(sig_blob);
  if(rc != SSH_OK){
    ssh_set_error_oom(session);
    ssh_buffer_reinit(session->out_buffer);
    return -1;
  }

  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    ssh_buffer_reinit(session->out_buffer);
    return -1;
  }

  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }
  SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
  session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;

  return 0;
}
Exemple #2
0
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string;
    ssh_string q_s_string;
    EC_KEY *ecdh_key;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = ssh_buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
        ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
        return SSH_ERROR;
    }
    session->next_crypto->ecdh_client_pubkey = q_c_string;

    /* Build server's keypair */

    ctx = BN_CTX_new();
    ecdh_key = EC_KEY_new_by_curve_name(NISTP256);
    if (ecdh_key == NULL) {
        ssh_set_error_oom(session);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    group = EC_KEY_get0_group(ecdh_key);
    EC_KEY_generate_key(ecdh_key);

    ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key);
    len = EC_POINT_point2oct(group,
                             ecdh_pubkey,
                             POINT_CONVERSION_UNCOMPRESSED,
                             NULL,
                             0,
                             ctx);

    q_s_string = ssh_string_new(len);
    if (q_s_string == NULL) {
        EC_KEY_free(ecdh_key);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    EC_POINT_point2oct(group,
                       ecdh_pubkey,
                       POINT_CONVERSION_UNCOMPRESSED,
                       ssh_string_data(q_s_string),
                       len,
                       ctx);
    BN_CTX_free(ctx);

    session->next_crypto->ecdh_privkey = ecdh_key;
    session->next_crypto->ecdh_server_pubkey = q_s_string;

    /* build k and session_id */
    rc = ecdh_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        return SSH_ERROR;
    }

    /* privkey is not allocated */
    rc = ssh_get_key_params(session, &privkey);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    rc = ssh_make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        return SSH_ERROR;
    }

    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(session->out_buffer,
                         "bSSS",
                         SSH2_MSG_KEXDH_REPLY,
                         session->next_crypto->server_pubkey, /* host's pubkey */
                         q_s_string, /* ecdh public key */
                         sig_blob); /* signature blob */

    ssh_string_free(sig_blob);

    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
    rc = ssh_packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    /* Send the MSG_NEWKEYS */
    rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
    if (rc < 0) {
        return SSH_ERROR;;
    }

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = ssh_packet_send(session);
    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
}
Exemple #3
0
static int dh_handshake_server(ssh_session session) {
  ssh_key privkey;
  //ssh_string pubkey_blob = NULL;
  ssh_string sig_blob;
  ssh_string f;

  if (dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  if (ssh_get_key_params(session,&privkey) != SSH_OK){
      ssh_string_free(f);
      return -1;
  }

  if (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    ssh_string_free(f);
    return -1;
  }

  if (make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    ssh_string_free(f);
    return -1;
  }

  sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
  if (sig_blob == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    ssh_string_free(f);
    return -1;
  }

  /* Free private keys as they should not be readable after this point */
  if (session->srv.rsa_key) {
      ssh_key_free(session->srv.rsa_key);
      session->srv.rsa_key = NULL;
  }
  if (session->srv.dsa_key) {
      ssh_key_free(session->srv.dsa_key);
      session->srv.dsa_key = NULL;
  }
#ifdef HAVE_ECC
  if (session->srv.ecdsa_key) {
      ssh_key_free(session->srv.ecdsa_key);
      session->srv.ecdsa_key = NULL;
  }
#endif

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 ||
      buffer_add_ssh_string(session->out_buffer,
              session->next_crypto->server_pubkey) < 0 ||
      buffer_add_ssh_string(session->out_buffer, f) < 0 ||
      buffer_add_ssh_string(session->out_buffer, sig_blob) < 0) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    buffer_reinit(session->out_buffer);
    ssh_string_free(f);
    ssh_string_free(sig_blob);
    return -1;
  }
  ssh_string_free(f);
  ssh_string_free(sig_blob);
  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    buffer_reinit(session->out_buffer);
    return -1;
  }

  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
  session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;

  return 0;
}
Exemple #4
0
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string = NULL;
    ssh_string q_s_string = NULL;
    EC_KEY *ecdh_key=NULL;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

    enter_function();

    /* Extract the client pubkey from the init packet */

    q_c_string = buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
      ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
      goto error;
    }
    session->next_crypto->ecdh_client_pubkey = q_c_string;

    /* Build server's keypair */

    ctx = BN_CTX_new();
    ecdh_key = EC_KEY_new_by_curve_name(NISTP256);
    group = EC_KEY_get0_group(ecdh_key);
    EC_KEY_generate_key(ecdh_key);
    ecdh_pubkey=EC_KEY_get0_public_key(ecdh_key);
    len = EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED,
        NULL,0,ctx);
    q_s_string=ssh_string_new(len);

    EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED,
        ssh_string_data(q_s_string),len,ctx);

    BN_CTX_free(ctx);
    session->next_crypto->ecdh_privkey = ecdh_key;
    session->next_crypto->ecdh_server_pubkey = q_s_string;

    buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY);
    /* build k and session_id */
    if (ecdh_build_k(session) < 0) {
      ssh_set_error(session, SSH_FATAL, "Cannot build k number");
      goto error;
    }
    if (ssh_get_key_params(session, &privkey) == SSH_ERROR)
        goto error;
    if (make_sessionid(session) != SSH_OK) {
      ssh_set_error(session, SSH_FATAL, "Could not create a session id");
      goto error;
    }

    /* add host's public key */
    buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey);
    /* add ecdh public key */
    buffer_add_ssh_string(session->out_buffer,q_s_string);
    /* add signature blob */
    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        goto error;
    }
    buffer_add_ssh_string(session->out_buffer, sig_blob);
    ssh_string_free(sig_blob);
    /* Free private keys as they should not be readable after this point */
    if (session->srv.rsa_key) {
        ssh_key_free(session->srv.rsa_key);
        session->srv.rsa_key = NULL;
    }
    if (session->srv.dsa_key) {
        ssh_key_free(session->srv.dsa_key);
        session->srv.dsa_key = NULL;
    }

    ssh_log(session,SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
    rc = packet_send(session);
    if (rc == SSH_ERROR)
        goto error;

    /* Send the MSG_NEWKEYS */
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
      goto error;
    }
    session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
    rc=packet_send(session);
    ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
    return rc;
  error:
    return SSH_ERROR;
}
Exemple #5
0
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
 * SSH_MSG_KEXDH_REPLY
 */
int ssh_server_curve25519_init(ssh_session_t * session, ssh_buffer_t * packet){
    /* ECDH keys */
    ssh_string_t * q_c_string;
    ssh_string_t * q_s_string;

    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key_t * privkey;
    ssh_string_t * sig_blob = NULL;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
        ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
        return SSH_ERROR;
    }
    if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
    	ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
    			(int)ssh_string_len(q_c_string));
    	ssh_string_free(q_c_string);
    	return SSH_ERROR;
    }

    memcpy(session->next_crypto->curve25519_client_pubkey,
    		ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
    ssh_string_free(q_c_string);
    /* Build server's keypair */

    rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
    if (rc == 0){
        ssh_set_error(session, SSH_FATAL, "PRNG error");
        return SSH_ERROR;
    }

    crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
  		  session->next_crypto->curve25519_privkey);

    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* build k and session_id */
    rc = ssh_curve25519_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        goto error;
    }

    /* privkey is not allocated */
    rc = ssh_get_key_params(session, &privkey);
    if (rc == SSH_ERROR) {
        goto error;
    }

    rc = make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        goto error;
    }

    /* add host's public key */
    rc = buffer_add_ssh_string(session->out_buffer,
                               session->next_crypto->server_pubkey);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* add ecdh public key */
    q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
    if (q_s_string == NULL) {
        goto error;
    }

    ssh_string_fill(q_s_string,
                    session->next_crypto->curve25519_server_pubkey,
                    CURVE25519_PUBKEY_SIZE);

    rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
    ssh_string_free(q_s_string);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }
    /* add signature blob */
    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        goto error;
    }

    rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
    ssh_string_free(sig_blob);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent");
    rc = packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    /* Send the MSG_NEWKEYS */
    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
    if (rc < 0) {
        goto error;
    }

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = packet_send(session);
    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
error:
    buffer_reinit(session->out_buffer);
    return SSH_ERROR;
}