コード例 #1
0
ファイル: kex.c プロジェクト: caidongyun/nullfxp
/* this is a public key in openssh's format */
static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
  ssh_buffer buffer = NULL;
  ssh_string rsa = NULL;
  ssh_string ret = NULL;

  buffer = ssh_buffer_new();
  rsa = ssh_string_from_char("ssh-rsa1");

  if (buffer_add_ssh_string(buffer, rsa) < 0) {
    goto error;
  }
  if (buffer_add_ssh_string(buffer, e) < 0) {
    goto error;
  }
  if (buffer_add_ssh_string(buffer, n) < 0) {
    goto error;
  }

  ret = ssh_string_new(ssh_buffer_get_len(buffer));
  if (ret == NULL) {
    goto error;
  }

  ssh_string_fill(ret, ssh_buffer_get_begin(buffer), ssh_buffer_get_len(buffer));
error:
  ssh_buffer_free(buffer);
  ssh_string_free(rsa);

  return ret;
}
コード例 #2
0
ファイル: pki_gcrypt.c プロジェクト: caidongyun/ssh-proxy
static int asn1_check_sequence(ssh_buffer_t * buffer) {
  unsigned char *j = NULL;
  unsigned char tmp;
  int i;
  uint32_t size;
  uint32_t padding;

  if (buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) {
    return 0;
  }

  size = asn1_get_len(buffer);
  if ((padding = ssh_buffer_get_len(buffer) - buffer->pos - size) > 0) {
    for (i = ssh_buffer_get_len(buffer) - buffer->pos - size,
         j = (unsigned char*)ssh_buffer_get_begin(buffer) + size + buffer->pos;
         i;
         i--, j++)
    {
      if (*j != padding) {                   /* padding is allowed */
        return 0;                            /* but nothing else */
      }
    }
  }

  return 1;
}
コード例 #3
0
ファイル: pki_gcrypt.c プロジェクト: caidongyun/ssh-proxy
static int privatekey_decrypt(int algo, int mode, unsigned int key_len,
                       unsigned char *iv, unsigned int iv_len,
                       ssh_buffer_t * data, ssh_auth_callback cb,
                       void *userdata,
                       const char *desc)
{
  char passphrase[MAX_PASSPHRASE_SIZE] = {0};
  unsigned char key[MAX_KEY_SIZE] = {0};
  unsigned char *tmp = NULL;
  gcry_cipher_hd_t cipher;
  int rc = -1;

  if (!algo) {
    return -1;
  }

  if (cb) {
    rc = (*cb)(desc, passphrase, MAX_PASSPHRASE_SIZE, 0, 0, userdata);
    if (rc < 0) {
      return -1;
    }
  } else if (cb == NULL && userdata != NULL) {
    snprintf(passphrase, MAX_PASSPHRASE_SIZE, "%s", (char *) userdata);
  }

  if (passphrase_to_key(passphrase, strlen(passphrase), iv, key, key_len) < 0) {
    return -1;
  }

  if (gcry_cipher_open(&cipher, algo, mode, 0)
      || gcry_cipher_setkey(cipher, key, key_len)
      || gcry_cipher_setiv(cipher, iv, iv_len)
      || (tmp = malloc(ssh_buffer_get_len(data) * sizeof (char))) == NULL
      || gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data),
                       ssh_buffer_get_begin(data), ssh_buffer_get_len(data))) {
    gcry_cipher_close(cipher);
    return -1;
  }

  memcpy(ssh_buffer_get_begin(data), tmp, ssh_buffer_get_len(data));

  SAFE_FREE(tmp);
  gcry_cipher_close(cipher);

  return 0;
}
コード例 #4
0
ファイル: gssapi.c プロジェクト: alexislitool/tmate
static int ssh_gssapi_send_mic(ssh_session session){
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER;
    ssh_buffer mic_buffer;
    int rc;

    SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC");

    mic_buffer = ssh_gssapi_build_mic(session);
    if (mic_buffer == NULL) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    mic_buf.length = ssh_buffer_get_len(mic_buffer);
    mic_buf.value = ssh_buffer_get_begin(mic_buffer);

    maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf);
    if (GSS_ERROR(maj_stat)){
        ssh_buffer_free(mic_buffer);
        ssh_gssapi_log_error(0, "generating MIC", maj_stat);
        return SSH_ERROR;
    }

    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_GSSAPI_MIC);
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    rc = buffer_add_u32(session->out_buffer, htonl(mic_token_buf.length));
    if (rc < 0) {
        ssh_buffer_free(mic_buffer);
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    rc = buffer_add_data(session->out_buffer, mic_token_buf.value, mic_token_buf.length);
    ssh_buffer_free(mic_buffer);
    if (rc < 0) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    return packet_send(session);
}
コード例 #5
0
ファイル: gssapi.c プロジェクト: Distrotech/libssh
static int ssh_gssapi_send_mic(ssh_session session){
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER;
    ssh_buffer mic_buffer;
    int rc;

    SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC");

    mic_buffer = ssh_gssapi_build_mic(session);
    if (mic_buffer == NULL) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    mic_buf.length = ssh_buffer_get_len(mic_buffer);
    mic_buf.value = ssh_buffer_get_begin(mic_buffer);

    maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf);
    if (GSS_ERROR(maj_stat)){
        ssh_buffer_free(mic_buffer);
        ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "generating MIC", maj_stat);
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(session->out_buffer,
                         "bdP",
                         SSH2_MSG_USERAUTH_GSSAPI_MIC,
                         mic_token_buf.length,
                         (size_t)mic_token_buf.length, mic_token_buf.value);
    if (rc != SSH_OK) {
        ssh_buffer_free(mic_buffer);
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    return packet_send(session);
}
コード例 #6
0
ファイル: pki.c プロジェクト: DouglasHeriot/libssh
/*
 * This function signs the session id as a string then
 * the content of sigbuf */
ssh_string ssh_pki_do_sign(ssh_session session,
                           ssh_buffer sigbuf,
                           const ssh_key privkey) {
    struct ssh_crypto_struct *crypto =
        session->current_crypto ? session->current_crypto :
                                  session->next_crypto;
    ssh_signature sig = NULL;
    ssh_string sig_blob;
    ssh_string session_id;
    int rc;

    if (privkey == NULL || !ssh_key_is_private(privkey)) {
        return NULL;
    }

    session_id = ssh_string_new(crypto->digest_len);
    if (session_id == NULL) {
        return NULL;
    }
    ssh_string_fill(session_id, crypto->session_id, crypto->digest_len);

    if (privkey->type == SSH_KEYTYPE_ECDSA) {
#ifdef HAVE_ECC
        unsigned char ehash[EVP_DIGEST_LEN] = {0};
        uint32_t elen;
        EVPCTX ctx;

        ctx = evp_init(privkey->ecdsa_nid);
        if (ctx == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        evp_update(ctx, session_id, ssh_string_len(session_id) + 4);
        evp_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
        evp_final(ctx, ehash, &elen);

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("Hash being signed", ehash, elen);
#endif

        sig = pki_do_sign(privkey, ehash, elen);
#endif
    } else if (privkey->type == SSH_KEYTYPE_ED25519){
        ssh_buffer buf;

        buf = ssh_buffer_new();
        if (buf == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        ssh_buffer_set_secure(buf);
        rc = ssh_buffer_pack(buf,
                             "SP",
                             session_id,
                             buffer_get_rest_len(sigbuf), buffer_get_rest(sigbuf));
        if (rc != SSH_OK) {
            ssh_string_free(session_id);
            ssh_buffer_free(buf);
            return NULL;
        }

        sig = pki_do_sign(privkey,
                          ssh_buffer_get_begin(buf),
                          ssh_buffer_get_len(buf));
        ssh_buffer_free(buf);
    } else {
        unsigned char hash[SHA_DIGEST_LEN] = {0};
        SHACTX ctx;

        ctx = sha1_init();
        if (ctx == NULL) {
            ssh_string_free(session_id);
            return NULL;
        }

        sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
        sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
        sha1_final(hash, ctx);

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
#endif

        sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
    }
    ssh_string_free(session_id);
    if (sig == NULL) {
        return NULL;
    }

    rc = ssh_pki_export_signature_blob(sig, &sig_blob);
    ssh_signature_free(sig);
    if (rc < 0) {
        return NULL;
    }

    return sig_blob;
}
コード例 #7
0
ファイル: dh.c プロジェクト: mwgoldsmith/ssh
int make_sessionid(ssh_session session) {
    ssh_string num = NULL;
    ssh_buffer server_hash = NULL;
    ssh_buffer client_hash = NULL;
    ssh_buffer buf = NULL;
    int rc = SSH_ERROR;

    buf = ssh_buffer_new();
    if (buf == NULL) {
        return rc;
    }

    rc = ssh_buffer_pack(buf,
                         "ss",
                         session->clientbanner,
                         session->serverbanner);
    if (rc == SSH_ERROR) {
        goto error;
    }

    if (session->client) {
        server_hash = session->in_hashbuf;
        client_hash = session->out_hashbuf;
    } else {
        server_hash = session->out_hashbuf;
        client_hash = session->in_hashbuf;
    }

    /*
     * Handle the two final fields for the KEXINIT message (RFC 4253 7.1):
     *
     *      boolean      first_kex_packet_follows
     *      uint32       0 (reserved for future extension)
     */
    rc = buffer_add_u8(server_hash, 0);
    if (rc < 0) {
        goto error;
    }
    rc = buffer_add_u32(server_hash, 0);
    if (rc < 0) {
        goto error;
    }

    /* These fields are handled for the server case in ssh_packet_kexinit. */
    if (session->client) {
        rc = buffer_add_u8(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
        rc = buffer_add_u32(client_hash, 0);
        if (rc < 0) {
            goto error;
        }
    }

    rc = ssh_buffer_pack(buf,
                         "dPdPS",
                         buffer_get_rest_len(client_hash),
                         buffer_get_rest_len(client_hash),
                         buffer_get_rest(client_hash),
                         buffer_get_rest_len(server_hash),
                         buffer_get_rest_len(server_hash),
                         buffer_get_rest(server_hash),
                         session->next_crypto->server_pubkey);

    if(rc != SSH_OK){
        goto error;
    }

    if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
            session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
        rc = ssh_buffer_pack(buf,
                             "BB",
                             session->next_crypto->e,
                             session->next_crypto->f);
        if (rc != SSH_OK) {
            goto error;
        }

#ifdef HAVE_ECDH
    } else if (session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) {
        if (session->next_crypto->ecdh_client_pubkey == NULL ||
            session->next_crypto->ecdh_server_pubkey == NULL) {
            SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
            goto error;
        }
        rc = ssh_buffer_pack(buf,
                             "SS",
                             session->next_crypto->ecdh_client_pubkey,
                             session->next_crypto->ecdh_server_pubkey);
        if (rc != SSH_OK) {
            goto error;
        }
#endif
#ifdef HAVE_CURVE25519
    } else if (session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG) {
        rc = ssh_buffer_pack(buf,
                             "dPdP",
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey,
                             CURVE25519_PUBKEY_SIZE,
                             (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey);

        if (rc != SSH_OK) {
            goto error;
        }
#endif
    }
    rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
    if (rc != SSH_OK) {
        goto error;
    }

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
#endif

    switch (session->next_crypto->kex_type) {
    case SSH_KEX_DH_GROUP1_SHA1:
    case SSH_KEX_DH_GROUP14_SHA1:
        session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
        session->next_crypto->mac_type = SSH_MAC_SHA1;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha1(buffer_get_rest(buf), buffer_get_rest_len(buf),
                                   session->next_crypto->secret_hash);
        break;
    case SSH_KEX_ECDH_SHA2_NISTP256:
    case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
        session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
        session->next_crypto->mac_type = SSH_MAC_SHA256;
        session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->secret_hash == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        sha256(buffer_get_rest(buf), buffer_get_rest_len(buf),
                                     session->next_crypto->secret_hash);
        break;
    }
    /* During the first kex, secret hash and session ID are equal. However, after
     * a key re-exchange, a new secret hash is calculated. This hash will not replace
     * but complement existing session id.
     */
    if (!session->next_crypto->session_id) {
        session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
        if (session->next_crypto->session_id == NULL) {
            ssh_set_error_oom(session);
            goto error;
        }
        memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
                session->next_crypto->digest_len);
    }
#ifdef DEBUG_CRYPTO
    printf("Session hash: \n");
    ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len);
    ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len);
#endif

    rc = SSH_OK;
error:
    ssh_buffer_free(buf);
    ssh_buffer_free(client_hash);
    ssh_buffer_free(server_hash);

    session->in_hashbuf = NULL;
    session->out_hashbuf = NULL;

    ssh_string_free(num);

    return rc;
}
コード例 #8
0
ファイル: packet.c プロジェクト: caidongyun/nullfxp
/** @internal
 * @handles a data received event. It then calls the handlers for the different packet types
 * or and exception handler callback.
 * @param user pointer to current ssh_session
 * @param data pointer to the data received
 * @len length of data received. It might not be enough for a complete packet
 * @returns number of bytes read and processed.
 */
int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user){
  ssh_session session=(ssh_session) user;
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->in_cipher->blocksize : 8);
  int current_macsize = session->current_crypto ? macsize : 0;
  unsigned char mac[30] = {0};
  char buffer[16] = {0};
  void *packet=NULL;
  int to_be_read;
  int rc;
  uint32_t len;
  uint8_t padding;
  size_t processed=0; /* number of byte processed from the callback */

  enter_function();

  switch(session->packet_state) {
    case PACKET_STATE_INIT:
    	if(receivedlen < blocksize){
    		/* We didn't receive enough data to read at least one block size, give up */
    		leave_function();
    		return 0;
    	}
      memset(&session->in_packet, 0, sizeof(PACKET));

      if (session->in_buffer) {
        if (buffer_reinit(session->in_buffer) < 0) {
          goto error;
        }
      } else {
        session->in_buffer = ssh_buffer_new();
        if (session->in_buffer == NULL) {
          goto error;
        }
      }

      memcpy(buffer,data,blocksize);
      processed += blocksize;
      len = packet_decrypt_len(session, buffer);

      if (buffer_add_data(session->in_buffer, buffer, blocksize) < 0) {
        goto error;
      }

      if(len > MAX_PACKET_LEN) {
        ssh_set_error(session, SSH_FATAL,
            "read_packet(): Packet len too high(%u %.4x)", len, len);
        goto error;
      }

      to_be_read = len - blocksize + sizeof(uint32_t);
      if (to_be_read < 0) {
        /* remote sshd sends invalid sizes? */
        ssh_set_error(session, SSH_FATAL,
            "given numbers of bytes left to be read < 0 (%d)!", to_be_read);
        goto error;
      }

      /* saves the status of the current operations */
      session->in_packet.len = len;
      session->packet_state = PACKET_STATE_SIZEREAD;
    case PACKET_STATE_SIZEREAD:
      len = session->in_packet.len;
      to_be_read = len - blocksize + sizeof(uint32_t) + current_macsize;
      /* if to_be_read is zero, the whole packet was blocksize bytes. */
      if (to_be_read != 0) {
        if(receivedlen - processed < (unsigned int)to_be_read){
        	/* give up, not enough data in buffer */
        	return processed;
        }

        packet = (unsigned char *)data + processed;
//        ssh_socket_read(session->socket,packet,to_be_read-current_macsize);

        ssh_log(session,SSH_LOG_PACKET,"Read a %d bytes packet",len);

        if (buffer_add_data(session->in_buffer, packet,
              to_be_read - current_macsize) < 0) {
          goto error;
        }
        processed += to_be_read - current_macsize;
      }

      if (session->current_crypto) {
        /*
         * decrypt the rest of the packet (blocksize bytes already
         * have been decrypted)
         */
        if (packet_decrypt(session,
              ((uint8_t*)buffer_get_rest(session->in_buffer) + blocksize),
              buffer_get_rest_len(session->in_buffer) - blocksize) < 0) {
          ssh_set_error(session, SSH_FATAL, "Decrypt error");
          goto error;
        }
        /* copy the last part from the incoming buffer */
        memcpy(mac,(unsigned char *)packet + to_be_read - current_macsize, macsize);

        if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
          ssh_set_error(session, SSH_FATAL, "HMAC error");
          goto error;
        }
        processed += current_macsize;
      }

      /* skip the size field which has been processed before */
      buffer_pass_bytes(session->in_buffer, sizeof(uint32_t));

      if (buffer_get_u8(session->in_buffer, &padding) == 0) {
        ssh_set_error(session, SSH_FATAL, "Packet too short to read padding");
        goto error;
      }

      ssh_log(session, SSH_LOG_PACKET,
          "%hhd bytes padding, %d bytes left in buffer",
          padding, buffer_get_rest_len(session->in_buffer));

      if (padding > buffer_get_rest_len(session->in_buffer)) {
        ssh_set_error(session, SSH_FATAL,
            "Invalid padding: %d (%d resting)",
            padding,
            buffer_get_rest_len(session->in_buffer));
#ifdef DEBUG_CRYPTO
        ssh_print_hexa("incrimined packet",
            ssh_buffer_get_begin(session->in_buffer),
            ssh_buffer_get_len(session->in_buffer));
#endif
        goto error;
      }
      buffer_pass_bytes_end(session->in_buffer, padding);

      ssh_log(session, SSH_LOG_PACKET,
          "After padding, %d bytes left in buffer",
          buffer_get_rest_len(session->in_buffer));
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
      if (session->current_crypto
          && session->current_crypto->do_compress_in
          && buffer_get_rest_len(session->in_buffer)) {
        ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ...");
        if (decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN) < 0) {
          goto error;
        }
      }
#endif
      session->recv_seq++;
      /* We don't want to rewrite a new packet while still executing the packet callbacks */
      session->packet_state = PACKET_STATE_PROCESSING;
      ssh_packet_parse_type(session);
      /* execute callbacks */
      ssh_packet_process(session, session->in_packet.type);
      session->packet_state = PACKET_STATE_INIT;
      if(processed < receivedlen){
      	/* Handle a potential packet left in socket buffer */
      	ssh_log(session,SSH_LOG_PACKET,"Processing %" PRIdS " bytes left in socket buffer",
      			receivedlen-processed);
      	rc = ssh_packet_socket_callback((char *)data + processed,
      			receivedlen - processed,user);
      	processed += rc;
      }
      leave_function();
      return processed;
    case PACKET_STATE_PROCESSING:
    	ssh_log(session, SSH_LOG_RARE, "Nested packet processing. Delaying.");
    	return 0;
  }

  ssh_set_error(session, SSH_FATAL,
      "Invalid state into packet_read2(): %d",
      session->packet_state);

error:
  leave_function();
  return processed;
}
コード例 #9
0
ファイル: pki_gcrypt.c プロジェクト: caidongyun/ssh-proxy
static ssh_buffer_t * privatekey_string_to_buffer(const char *pkey, int type,
                ssh_auth_callback cb, void *userdata, const char *desc) {
    ssh_buffer_t * buffer = NULL;
    ssh_buffer_t * out = NULL;
    const char *p;
    unsigned char *iv = NULL;
    const char *header_begin;
    const char *header_end;
    unsigned int header_begin_size;
    unsigned int header_end_size;
    unsigned int key_len = 0;
    unsigned int iv_len = 0;
    int algo = 0;
    int mode = 0;
    int len;

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        return NULL;
    }

    switch(type) {
        case SSH_KEYTYPE_DSS:
            header_begin = DSA_HEADER_BEGIN;
            header_end = DSA_HEADER_END;
            break;
        case SSH_KEYTYPE_RSA:
            header_begin = RSA_HEADER_BEGIN;
            header_end = RSA_HEADER_END;
            break;
        default:
            ssh_buffer_free(buffer);
            return NULL;
    }

    header_begin_size = strlen(header_begin);
    header_end_size = strlen(header_end);

    p = pkey;
    len = 0;
    get_next_line(p, len);

    while(len > 0 && strncmp(p, header_begin, header_begin_size)) {
        /* skip line */
        get_next_line(p, len);
    }
    if(len < 0) {
        /* no header found */
        return NULL;
    }
    /* skip header line */
    get_next_line(p, len);

    if (len > 11 && strncmp("Proc-Type: 4,ENCRYPTED", p, 11) == 0) {
        /* skip line */
        get_next_line(p, len);

        if (len > 10 && strncmp("DEK-Info: ", p, 10) == 0) {
            p += 10;
            len = 0;
            get_next_line(p, len);
            if (privatekey_dek_header(p, len, &algo, &mode, &key_len,
                        &iv, &iv_len) < 0) {
                ssh_buffer_free(buffer);
                SAFE_FREE(iv);
                return NULL;
            }
        } else {
            ssh_buffer_free(buffer);
            SAFE_FREE(iv);
            return NULL;
        }
    } else {
        if(len > 0) {
            if (buffer_add_data(buffer, p, len) < 0) {
                ssh_buffer_free(buffer);
                SAFE_FREE(iv);
                return NULL;
            }
        }
    }

    get_next_line(p, len);
    while(len > 0 && strncmp(p, header_end, header_end_size) != 0) {
        if (buffer_add_data(buffer, p, len) < 0) {
            ssh_buffer_free(buffer);
            SAFE_FREE(iv);
            return NULL;
        }
        get_next_line(p, len);
    }

    if (len == -1 || strncmp(p, header_end, header_end_size) != 0) {
        ssh_buffer_free(buffer);
        SAFE_FREE(iv);
        return NULL;
    }

    if (buffer_add_data(buffer, "\0", 1) < 0) {
        ssh_buffer_free(buffer);
        SAFE_FREE(iv);
        return NULL;
    }

    out = base64_to_bin(ssh_buffer_get_begin(buffer));
    ssh_buffer_free(buffer);
    if (out == NULL) {
        SAFE_FREE(iv);
        return NULL;
    }

    if (algo) {
        if (privatekey_decrypt(algo, mode, key_len, iv, iv_len, out,
                    cb, userdata, desc) < 0) {
            ssh_buffer_free(out);
            SAFE_FREE(iv);
            return NULL;
        }
    }
    SAFE_FREE(iv);

    return out;
}
コード例 #10
0
ファイル: dh.c プロジェクト: ToThePradoHotel/libssh
int make_sessionid(ssh_session session) {
  SHACTX ctx;
  ssh_string num = NULL;
  ssh_string str = NULL;
  ssh_buffer server_hash = NULL;
  ssh_buffer client_hash = NULL;
  ssh_buffer buf = NULL;
  uint32_t len;
  int rc = SSH_ERROR;

  enter_function();

  ctx = sha1_init();
  if (ctx == NULL) {
    return rc;
  }

  buf = ssh_buffer_new();
  if (buf == NULL) {
    return rc;
  }

  str = ssh_string_from_char(session->clientbanner);
  if (str == NULL) {
    goto error;
  }

  if (buffer_add_ssh_string(buf, str) < 0) {
    goto error;
  }
  ssh_string_free(str);

  str = ssh_string_from_char(session->serverbanner);
  if (str == NULL) {
    goto error;
  }

  if (buffer_add_ssh_string(buf, str) < 0) {
    goto error;
  }

  if (session->client) {
    server_hash = session->in_hashbuf;
    client_hash = session->out_hashbuf;
  } else {
    server_hash = session->out_hashbuf;
    client_hash = session->in_hashbuf;
  }

  if (buffer_add_u32(server_hash, 0) < 0) {
    goto error;
  }
  if (buffer_add_u8(server_hash, 0) < 0) {
    goto error;
  }
  if (buffer_add_u32(client_hash, 0) < 0) {
    goto error;
  }
  if (buffer_add_u8(client_hash, 0) < 0) {
    goto error;
  }

  len = ntohl(buffer_get_rest_len(client_hash));
  if (buffer_add_u32(buf,len) < 0) {
    goto error;
  }
  if (buffer_add_data(buf, buffer_get_rest(client_hash),
        buffer_get_rest_len(client_hash)) < 0) {
    goto error;
  }

  len = ntohl(buffer_get_rest_len(server_hash));
  if (buffer_add_u32(buf, len) < 0) {
    goto error;
  }
  if (buffer_add_data(buf, buffer_get_rest(server_hash),
        buffer_get_rest_len(server_hash)) < 0) {
    goto error;
  }

  len = ssh_string_len(session->next_crypto->server_pubkey) + 4;
  if (buffer_add_data(buf, session->next_crypto->server_pubkey, len) < 0) {
    goto error;
  }

  num = make_bignum_string(session->next_crypto->e);
  if (num == NULL) {
    goto error;
  }

  len = ssh_string_len(num) + 4;
  if (buffer_add_data(buf, num, len) < 0) {
    goto error;
  }

  ssh_string_free(num);
  num = make_bignum_string(session->next_crypto->f);
  if (num == NULL) {
    goto error;
  }

  len = ssh_string_len(num) + 4;
  if (buffer_add_data(buf, num, len) < 0) {
    goto error;
  }

  ssh_string_free(num);
  num = make_bignum_string(session->next_crypto->k);
  if (num == NULL) {
    goto error;
  }

  len = ssh_string_len(num) + 4;
  if (buffer_add_data(buf, num, len) < 0) {
    goto error;
  }

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
#endif

  sha1_update(ctx, buffer_get_rest(buf), buffer_get_rest_len(buf));
  sha1_final(session->next_crypto->session_id, ctx);

#ifdef DEBUG_CRYPTO
  printf("Session hash: ");
  ssh_print_hexa("session id", session->next_crypto->session_id, SHA_DIGEST_LEN);
#endif

  rc = SSH_OK;
error:
  ssh_buffer_free(buf);
  ssh_buffer_free(client_hash);
  ssh_buffer_free(server_hash);

  session->in_hashbuf = NULL;
  session->out_hashbuf = NULL;

  ssh_string_free(str);
  ssh_string_free(num);

  leave_function();

  return rc;
}
コード例 #11
0
ファイル: packet1.c プロジェクト: rofl0r/libssh
int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user) {
  void *packet = NULL;
  int to_be_read;
  size_t processed=0;
  uint32_t padding;
  uint32_t crc;
  uint32_t len;
  ssh_session session=(ssh_session)user;


  switch (session->packet_state){
    case PACKET_STATE_INIT:
      memset(&session->in_packet, 0, sizeof(PACKET));

      if (session->in_buffer) {
        if (buffer_reinit(session->in_buffer) < 0) {
          goto error;
        }
      } else {
        session->in_buffer = ssh_buffer_new();
        if (session->in_buffer == NULL) {
          goto error;
        }
      }
      /* must have at least enough bytes for size */
      if(receivedlen < sizeof(uint32_t)){

        return 0;
      }
      memcpy(&len,data,sizeof(uint32_t));
      processed += sizeof(uint32_t);

      /* len is not encrypted */
      len = ntohl(len);
      if (len > MAX_PACKET_LEN) {
        ssh_set_error(session, SSH_FATAL,
            "read_packet(): Packet len too high (%u %.8x)", len, len);
        goto error;
      }

      ssh_log(session, SSH_LOG_PACKET, "Reading a %d bytes packet", len);

      session->in_packet.len = len;
      session->packet_state = PACKET_STATE_SIZEREAD;
    case PACKET_STATE_SIZEREAD:
      len = session->in_packet.len;
      /* SSH-1 has a fixed padding lenght */
      padding = 8 - (len % 8);
      to_be_read = len + padding;
      if(to_be_read + processed > receivedlen){
        /* wait for rest of packet */

        return processed;
      }
      /* it is _not_ possible that to_be_read be < 8. */
      packet = (char *)data + processed;

      if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
        SAFE_FREE(packet);
        goto error;
      }
      processed += to_be_read;
#ifdef DEBUG_CRYPTO
      ssh_print_hexa("read packet:", ssh_buffer_get_begin(session->in_buffer),
          ssh_buffer_get_len(session->in_buffer));
#endif
      if (session->current_crypto) {
        /*
         * We decrypt everything, missing the lenght part (which was
         * previously read, unencrypted, and is not part of the buffer
         */
        if (packet_decrypt(session,
              ssh_buffer_get_begin(session->in_buffer),
              ssh_buffer_get_len(session->in_buffer)) < 0) {
          ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
          goto error;
        }
      }
#ifdef DEBUG_CRYPTO
      ssh_print_hexa("read packet decrypted:", ssh_buffer_get_begin(session->in_buffer),
          ssh_buffer_get_len(session->in_buffer));
#endif
      ssh_log(session, SSH_LOG_PACKET, "%d bytes padding", padding);
      if(((len + padding) != buffer_get_rest_len(session->in_buffer)) ||
          ((len + padding) < sizeof(uint32_t))) {
        ssh_log(session, SSH_LOG_RARE, "no crc32 in packet");
        ssh_set_error(session, SSH_FATAL, "no crc32 in packet");
        goto error;
      }

      memcpy(&crc,
          (unsigned char *)buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(uint32_t),
          sizeof(uint32_t));
      buffer_pass_bytes_end(session->in_buffer, sizeof(uint32_t));
      crc = ntohl(crc);
      if (ssh_crc32(buffer_get_rest(session->in_buffer),
            (len + padding) - sizeof(uint32_t)) != crc) {
#ifdef DEBUG_CRYPTO
        ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer),
            len + padding - sizeof(uint32_t));
#endif
        ssh_log(session, SSH_LOG_RARE, "Invalid crc32");
        ssh_set_error(session, SSH_FATAL,
            "Invalid crc32: expected %.8x, got %.8x",
            crc,
            ssh_crc32(buffer_get_rest(session->in_buffer),
              len + padding - sizeof(uint32_t)));
        goto error;
      }
      /* pass the padding */
      buffer_pass_bytes(session->in_buffer, padding);
      ssh_log(session, SSH_LOG_PACKET, "The packet is valid");

/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
    if(session->current_crypto && session->current_crypto->do_compress_in){
        decompress_buffer(session,session->in_buffer);
    }
#endif
*/
      session->recv_seq++;
      /* We don't want to rewrite a new packet while still executing the packet callbacks */
      session->packet_state = PACKET_STATE_PROCESSING;
      ssh_packet_parse_type(session);
      /* execute callbacks */
      ssh_packet_process(session, session->in_packet.type);
      session->packet_state = PACKET_STATE_INIT;
      if(processed < receivedlen){
        int rc;
        /* Handle a potential packet left in socket buffer */
        ssh_log(session,SSH_LOG_PACKET,"Processing %" PRIdS " bytes left in socket buffer",
            receivedlen-processed);
        rc = ssh_packet_socket_callback1((char *)data + processed,
            receivedlen - processed,user);
        processed += rc;
      }

      return processed;
    case PACKET_STATE_PROCESSING:
      ssh_log(session, SSH_LOG_RARE, "Nested packet processing. Delaying.");
      return 0;
  }

error:
  session->session_state=SSH_SESSION_STATE_ERROR;

  return processed;
}
コード例 #12
0
ファイル: packet1.c プロジェクト: rofl0r/libssh
int packet_send1(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  uint32_t currentlen = ssh_buffer_get_len(session->out_buffer) + sizeof(uint32_t);
  char padstring[32] = {0};
  int rc = SSH_ERROR;
  uint32_t finallen;
  uint32_t crc;
  uint8_t padding;


  ssh_log(session,SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen);

/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
  if (session->current_crypto && session->current_crypto->do_compress_out) {
    if (compress_buffer(session, session->out_buffer) < 0) {
      goto error;
    }
    currentlen = buffer_get_len(session->out_buffer);
  }
#endif
*/
  padding = blocksize - (currentlen % blocksize);
  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  } else {
    memset(padstring, 0, padding);
  }

  finallen = htonl(currentlen);
  ssh_log(session, SSH_LOG_PACKET,
      "%d bytes after comp + %d padding bytes = %d bytes packet",
      currentlen, padding, ntohl(finallen));

  if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
    goto error;
  }
  if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
    goto error;
  }

  crc = ssh_crc32((char *)ssh_buffer_get_begin(session->out_buffer) + sizeof(uint32_t),
      ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));

  if (buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) {
    goto error;
  }

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Clear packet", ssh_buffer_get_begin(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
#endif

  packet_encrypt(session, (unsigned char *)ssh_buffer_get_begin(session->out_buffer) + sizeof(uint32_t),
      ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("encrypted packet",ssh_buffer_get_begin(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
#endif
  rc=ssh_socket_write(session->socket, ssh_buffer_get_begin(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
  if(rc== SSH_ERROR) {
    goto error;
  }

  session->send_seq++;

  if (buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:

  return rc;     /* SSH_OK, AGAIN or ERROR */
}
コード例 #13
0
ファイル: ssh.c プロジェクト: isdrupter/busybotnet
/* channel_select base main loop, with a standard select(2)
 */
static void select_loop(ssh_session session,ssh_channel channel){
    fd_set fds;
    struct timeval timeout;
    char buffer[4096];
    ssh_buffer readbuf=ssh_buffer_new();
    ssh_channel channels[2];
    int lus;
    int eof=0;
    int maxfd;
    int ret;
    while(channel){
       /* when a signal is caught, ssh_select will return
         * with SSH_EINTR, which means it should be started
         * again. It lets you handle the signal the faster you
         * can, like in this window changed example. Of course, if
         * your signal handler doesn't call libssh at all, you're
         * free to handle signals directly in sighandler.
         */
        do{
            FD_ZERO(&fds);
            if(!eof)
                FD_SET(0,&fds);
            timeout.tv_sec=30;
            timeout.tv_usec=0;
            FD_SET(ssh_get_fd(session),&fds);
            maxfd=ssh_get_fd(session)+1;
            ret=select(maxfd,&fds,NULL,NULL,&timeout);
            if(ret==EINTR)
                continue;
            if(FD_ISSET(0,&fds)){
                lus=read(0,buffer,sizeof(buffer));
                if(lus)
                    ssh_channel_write(channel,buffer,lus);
                else {
                    eof=1;
                    ssh_channel_send_eof(channel);
                }
            }
            if(FD_ISSET(ssh_get_fd(session),&fds)){
                ssh_set_fd_toread(session);
            }
            channels[0]=channel; // set the first channel we want to read from
            channels[1]=NULL;
            ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
            if(signal_delayed)
                sizechanged();
        } while (ret==EINTR || ret==SSH_EINTR);

        // we already looked for input from stdin. Now, we are looking for input from the channel

        if(channel && ssh_channel_is_closed(channel)){
            ssh_channel_free(channel);
            channel=NULL;
            channels[0]=NULL;
        }
        if(channels[0]){
            while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
                lus=channel_read_buffer(channel,readbuf,0,0);
                if(lus==-1){
                    fprintf(stderr, "Error reading channel: %s\n",
                        ssh_get_error(session));
                    return;
                }
                if(lus==0){
                    ssh_channel_free(channel);
                    channel=channels[0]=NULL;
                } else
                    if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
                      fprintf(stderr, "Error writing to buffer\n");
                      return;
                    }
            }
            while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
                lus=channel_read_buffer(channel,readbuf,0,1);
                if(lus==-1){
                    fprintf(stderr, "Error reading channel: %s\n",
                        ssh_get_error(session));
                    return;
                }
                if(lus==0){
                    ssh_channel_free(channel);
                    channel=channels[0]=NULL;
                } else
                    if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
                      fprintf(stderr, "Error writing to buffer\n");
                      return;
                    }
            }
        }
        if(channel && ssh_channel_is_closed(channel)){
            ssh_channel_free(channel);
            channel=NULL;
        }
    }
    ssh_buffer_free(readbuf);
}
コード例 #14
0
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
                                          const char *passphrase,
                                          ssh_auth_callback auth_fn,
                                          void *auth_data)
{
    ssh_buffer buffer;
    ssh_string str = NULL;
    ssh_string pubkey_s=NULL;
    ssh_buffer privkey_buffer = NULL;
    uint32_t rnd;
    uint32_t rounds = 16;
    ssh_string salt=NULL;
    ssh_string kdf_options=NULL;
    int to_encrypt=0;
    unsigned char *b64;
    uint32_t str_len, len;
    int rc;

    if (privkey == NULL) {
        return NULL;
    }
    if (privkey->type != SSH_KEYTYPE_ED25519){
        ssh_pki_log("Unsupported key type %s", privkey->type_c);
        return NULL;
    }
    if (passphrase != NULL || auth_fn != NULL){
        ssh_pki_log("Enabling encryption for private key export");
        to_encrypt = 1;
    }
    buffer = ssh_buffer_new();
    pubkey_s = pki_publickey_to_blob(privkey);
    if(buffer == NULL || pubkey_s == NULL){
        goto error;
    }
    ssh_get_random(&rnd, sizeof(rnd), 0);

    privkey_buffer = ssh_buffer_new();
    if (privkey_buffer == NULL) {
        goto error;
    }

    /* checkint1 & 2 */
    rc = ssh_buffer_pack(privkey_buffer,
                         "dd",
                         rnd,
                         rnd);
    if (rc == SSH_ERROR){
        goto error;
    }

    rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer);
    if (rc == SSH_ERROR){
        goto error;
    }

    /* comment */
    rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */);
    if (rc == SSH_ERROR){
        goto error;
    }

    if (to_encrypt){
        ssh_buffer kdf_buf;

        kdf_buf = ssh_buffer_new();
        if (kdf_buf == NULL) {
            goto error;
        }

        salt = ssh_string_new(16);
        if (salt == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        ssh_get_random(ssh_string_data(salt),16, 0);
        ssh_buffer_pack(kdf_buf, "Sd", salt, rounds);
        kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf));
        if (kdf_options == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        memcpy(ssh_string_data(kdf_options),
               ssh_buffer_get_begin(kdf_buf),
               ssh_buffer_get_len(kdf_buf));
        ssh_buffer_free(kdf_buf);
        rc = pki_private_key_encrypt(privkey_buffer,
                                     passphrase,
                                     "aes128-cbc",
                                     "bcrypt",
                                     auth_fn,
                                     auth_data,
                                     rounds,
                                     salt);
        if (rc != SSH_OK){
            goto error;
        }
    } else {
        kdf_options = ssh_string_new(0);
    }

    rc = ssh_buffer_pack(buffer,
                         "PssSdSdP",
                         (size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC,
                         to_encrypt ? "aes128-cbc" : "none", /* ciphername */
                         to_encrypt ? "bcrypt" : "none", /* kdfname */
                         kdf_options, /* kdfoptions */
                         (uint32_t) 1, /* nkeys */
                         pubkey_s,
                         (uint32_t)ssh_buffer_get_len(privkey_buffer),
                         /* rest of buffer is a string */
                         (size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get_begin(privkey_buffer));
    if (rc != SSH_OK) {
        goto error;
    }

    b64 = bin_to_base64(ssh_buffer_get_begin(buffer),
                        ssh_buffer_get_len(buffer));
    if (b64 == NULL){
        goto error;
    }

    /* we can reuse the buffer */
    ssh_buffer_reinit(buffer);
    rc = ssh_buffer_pack(buffer,
                         "tttttt",
                         OPENSSH_HEADER_BEGIN,
                         "\n",
                         b64,
                         "\n",
                         OPENSSH_HEADER_END,
                         "\n");
    BURN_BUFFER(b64, strlen((char *)b64));
    SAFE_FREE(b64);

    if (rc != SSH_OK){
        goto error;
    }

    str = ssh_string_new(ssh_buffer_get_len(buffer));
    if (str == NULL){
        goto error;
    }

    str_len = ssh_buffer_get_len(buffer);
    len = buffer_get_data(buffer, ssh_string_data(str), str_len);
    if (str_len != len) {
        ssh_string_free(str);
        str = NULL;
    }

error:
    if (privkey_buffer != NULL) {
        void *bufptr = ssh_buffer_get_begin(privkey_buffer);
        BURN_BUFFER(bufptr, ssh_buffer_get_len(privkey_buffer));
        ssh_buffer_free(privkey_buffer);
    }
    SAFE_FREE(pubkey_s);
    SAFE_FREE(kdf_options);
    SAFE_FREE(salt);
    if (buffer != NULL) {
        ssh_buffer_free(buffer);
    }

    return str;
}
コード例 #15
0
/** @internal
 * @brief encrypts an ed25519 private key blob
 *
 */
static int pki_private_key_encrypt(ssh_buffer privkey_buffer,
                                   const char* passphrase,
                                   const char *ciphername,
                                   const char *kdfname,
                                   ssh_auth_callback auth_fn,
                                   void *auth_data,
                                   uint32_t rounds,
                                   ssh_string salt)
{
    struct ssh_cipher_struct *ciphers = ssh_get_ciphertab();
    struct ssh_cipher_struct cipher;
    uint8_t key_material[128];
    size_t key_material_len;
    char passphrase_buffer[128];
    int rc;
    int i;
    uint8_t padding = 1;
    int cmp;

    cmp = strcmp(ciphername, "none");
    if (cmp == 0){
        /* no encryption required */
        return SSH_OK;
    }

    for (i = 0; ciphers[i].name != NULL; i++) {
        cmp = strcmp(ciphername, ciphers[i].name);
        if (cmp == 0){
            memcpy(&cipher, &ciphers[i], sizeof(cipher));
            break;
        }
    }

    if (ciphers[i].name == NULL){
        SSH_LOG(SSH_LOG_WARN, "Unsupported cipher %s", ciphername);
        return SSH_ERROR;
    }

    cmp = strcmp(kdfname, "bcrypt");
    if (cmp != 0){
        SSH_LOG(SSH_LOG_WARN, "Unsupported KDF %s", kdfname);
        return SSH_ERROR;
    }
    while (ssh_buffer_get_len(privkey_buffer) % cipher.blocksize != 0) {
        rc = buffer_add_u8(privkey_buffer, padding);
        if (rc < 0) {
            return SSH_ERROR;
        }
        padding++;
    }

    /* We need material for key (keysize bits / 8) and IV (blocksize)  */
    key_material_len =  cipher.keysize/8 + cipher.blocksize;
    if (key_material_len > sizeof(key_material)){
        ssh_pki_log("Key material too big");
        return SSH_ERROR;
    }

    ssh_pki_log("Encryption: %d key, %d IV, %d rounds, %zu bytes salt",
                cipher.keysize/8,
                cipher.blocksize, rounds, ssh_string_len(salt));

    if (passphrase == NULL){
        if (auth_fn == NULL){
            ssh_pki_log("No passphrase provided");
            return SSH_ERROR;
        }
        rc = auth_fn("Passphrase",
                     passphrase_buffer,
                     sizeof(passphrase_buffer),
                     0,
                     0,
                     auth_data);
        if (rc != SSH_OK){
            return SSH_ERROR;
        }
        passphrase = passphrase_buffer;
    }

    rc = bcrypt_pbkdf(passphrase,
                      strlen(passphrase),
                      ssh_string_data(salt),
                      ssh_string_len(salt),
                      key_material,
                      key_material_len,
                      rounds);
    if (rc < 0){
        return SSH_ERROR;
    }

    cipher.set_encrypt_key(&cipher,
                           key_material,
                           key_material + cipher.keysize/8);
    cipher.encrypt(&cipher,
                   ssh_buffer_get_begin(privkey_buffer),
                   ssh_buffer_get_begin(privkey_buffer),
                   ssh_buffer_get_len(privkey_buffer));
    ssh_cipher_clear(&cipher);
    BURN_BUFFER(passphrase_buffer, sizeof(passphrase_buffer));

    return SSH_OK;
}
コード例 #16
0
ファイル: legacy.c プロジェクト: rofl0r/libssh
void *buffer_get(ssh_buffer buffer){
  return ssh_buffer_get_begin(buffer);
}