Beispiel #1
0
static int build_session_id1(ssh_session session, ssh_string servern,
    ssh_string hostn) {
  MD5CTX md5 = NULL;

  md5 = md5_init();
  if (md5 == NULL) {
    return -1;
  }

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("host modulus",ssh_string_data(hostn),ssh_string_len(hostn));
  ssh_print_hexa("server modulus",ssh_string_data(servern),ssh_string_len(servern));
#endif
  md5_update(md5,ssh_string_data(hostn),ssh_string_len(hostn));
  md5_update(md5,ssh_string_data(servern),ssh_string_len(servern));
  md5_update(md5,session->next_crypto->server_kex.cookie,8);
  if(session->next_crypto->session_id != NULL)
      SAFE_FREE(session->next_crypto->session_id);
  session->next_crypto->session_id = malloc(MD5_DIGEST_LEN);
  if(session->next_crypto->session_id == NULL){
      ssh_set_error_oom(session);
      return SSH_ERROR;
  }
  md5_final(session->next_crypto->session_id,md5);
#ifdef DEBUG_CRYPTO
  ssh_print_hexa("session_id",session->next_crypto->session_id,MD5_DIGEST_LEN);
#endif

  return 0;
}
int pki_privkey_build_rsa(ssh_key key,
                          ssh_string n,
                          ssh_string e,
                          ssh_string d,
                          ssh_string iqmp,
                          ssh_string p,
                          ssh_string q)
{
    mbedtls_rsa_context *rsa = NULL;
    const mbedtls_pk_info_t *pk_info = NULL;
    int rc;

    key->rsa = malloc(sizeof(mbedtls_pk_context));
    if (key->rsa == NULL) {
        return SSH_ERROR;
    }

    mbedtls_pk_init(key->rsa);
    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
    mbedtls_pk_setup(key->rsa, pk_info);

    rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
    if (rc == 0) {
        goto fail;
    }

    rsa = mbedtls_pk_rsa(*key->rsa);
    rc = mbedtls_rsa_import_raw(rsa,
                                ssh_string_data(n), ssh_string_len(n),
                                ssh_string_data(p), ssh_string_len(p),
                                ssh_string_data(q), ssh_string_len(q),
                                ssh_string_data(d), ssh_string_len(d),
                                ssh_string_data(e), ssh_string_len(e));
    if (rc != 0) {
        SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key");
        goto fail;
    }

    rc = mbedtls_rsa_complete(rsa);
    if (rc != 0) {
        SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key");
        goto fail;
    }

    rc = mbedtls_rsa_check_privkey(rsa);
    if (rc != 0) {
        SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key");
        goto fail;
    }

    return SSH_OK;

fail:
    mbedtls_pk_free(key->rsa);
    SAFE_FREE(key->rsa);
    return SSH_ERROR;
}
static void torture_pubkey_generate_from_privkey(void **state) {
    ssh_session session = *state;
    ssh_private_key privkey = NULL;
    ssh_public_key pubkey = NULL;
    ssh_string pubkey_orig = NULL;
    ssh_string pubkey_new = NULL;
    char pubkey_line_orig[512] = {0};
    char pubkey_line_new[512] = {0};
    int type_orig = 0;
    int type_new = 0;
    int rc;

    /* read the publickey */
    rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey_orig,
        &type_orig);
    assert_true(rc == 0);
    assert_true(pubkey_orig != NULL);

    rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_orig,
        sizeof(pubkey_line_orig));
    assert_true(rc == 0);

    /* remove the public key, generate it from the private key and write it. */
    unlink(LIBSSH_RSA_TESTKEY ".pub");

    privkey = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL);
    assert_true(privkey != NULL);

    pubkey = publickey_from_privatekey(privkey);
    assert_true(pubkey != NULL);
    type_new = privkey->type;
    privatekey_free(privkey);

    pubkey_new = publickey_to_string(pubkey);
    publickey_free(pubkey);

    assert_true(pubkey_new != NULL);

    assert_true(ssh_string_len(pubkey_orig) == ssh_string_len(pubkey_new));
    assert_memory_equal(ssh_string_data(pubkey_orig),
                        ssh_string_data(pubkey_new),
                        ssh_string_len(pubkey_orig));

    rc = ssh_publickey_to_file(session, LIBSSH_RSA_TESTKEY ".pub", pubkey_new, type_new);
    assert_true(rc == 0);

    rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_new,
        sizeof(pubkey_line_new));
    assert_true(rc == 0);

    assert_string_equal(pubkey_line_orig, pubkey_line_new);

    ssh_string_free(pubkey_orig);
    ssh_string_free(pubkey_new);
}
Beispiel #4
0
int pki_pubkey_build_rsa(ssh_key key,
                         ssh_string e,
                         ssh_string n) {
    gcry_sexp_build(&key->rsa, NULL,
                    "(public-key(rsa(n %b)(e %b)))",
                    ssh_string_len(n), ssh_string_data(n),
                    ssh_string_len(e),ssh_string_data(e));
    if (key->rsa == NULL) {
        return SSH_ERROR;
    }

    return SSH_OK;
}
Beispiel #5
0
static int ecdh_build_k(ssh_session session) {
  const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
  EC_POINT *pubkey;
  void *buffer;
  int len = (EC_GROUP_get_degree(group) + 7) / 8;
  bignum_CTX ctx = bignum_ctx_new();
  if (ctx == NULL) {
    return -1;
  }

  session->next_crypto->k = bignum_new();
  if (session->next_crypto->k == NULL) {
    bignum_ctx_free(ctx);
    return -1;
  }

  pubkey = EC_POINT_new(group);
  if (pubkey == NULL) {
    bignum_ctx_free(ctx);
    return -1;
  }

  if (session->server)
      EC_POINT_oct2point(group,pubkey,ssh_string_data(session->next_crypto->ecdh_client_pubkey),
              ssh_string_len(session->next_crypto->ecdh_client_pubkey),ctx);
  else
      EC_POINT_oct2point(group,pubkey,ssh_string_data(session->next_crypto->ecdh_server_pubkey),
              ssh_string_len(session->next_crypto->ecdh_server_pubkey),ctx);
  buffer = malloc(len);
  ECDH_compute_key(buffer,len,pubkey,session->next_crypto->ecdh_privkey,NULL);
  EC_POINT_free(pubkey);
  BN_bin2bn(buffer,len,session->next_crypto->k);
  free(buffer);
  EC_KEY_free(session->next_crypto->ecdh_privkey);
  session->next_crypto->ecdh_privkey=NULL;
#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Session server cookie",
                   session->next_crypto->server_kex.cookie, 16);
    ssh_print_hexa("Session client cookie",
                   session->next_crypto->client_kex.cookie, 16);
    ssh_print_bignum("Shared secret key", session->next_crypto->k);
#endif

#ifdef HAVE_LIBCRYPTO
  bignum_ctx_free(ctx);
#endif

  return 0;
}
Beispiel #6
0
/*
 * This function will return you a new handle to give the client.
 * the function accepts an info that can be retrieved later with
 * the handle. Care is given that a corrupted handle won't give a
 * valid info (or worse).
 */
ssh_string sftp_handle_alloc(sftp_session sftp, void *info) {
  ssh_string ret;
  uint32_t val;
  int i;

  if (sftp->handles == NULL) {
    sftp->handles = calloc(SFTP_HANDLES, sizeof(void *));
    if (sftp->handles == NULL) {
      return NULL;
    }
  }

  for (i = 0; i < SFTP_HANDLES; i++) {
    if (sftp->handles[i] == NULL) {
      break;
    }
  }

  if (i == SFTP_HANDLES) {
    return NULL; /* no handle available */
  }

  val = i;
  ret = ssh_string_new(4);
  if (ret == NULL) {
    return NULL;
  }

  memcpy(ssh_string_data(ret), &val, sizeof(uint32_t));
  sftp->handles[i] = info;

  return ret;
}
Beispiel #7
0
/**
 * @deprecated Use ssh_get_publickey_hash()
 */
int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) {
  ssh_string pubkey;
  MD5CTX ctx;
  unsigned char *h;

  if (session == NULL || hash == NULL) {
    return SSH_ERROR;
  }
  *hash = NULL;
  if (session->current_crypto == NULL ||
      session->current_crypto->server_pubkey == NULL){
    ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
    return SSH_ERROR;
  }

  h = malloc(sizeof(unsigned char) * MD5_DIGEST_LEN);
  if (h == NULL) {
    return SSH_ERROR;
  }

  ctx = md5_init();
  if (ctx == NULL) {
    SAFE_FREE(h);
    return SSH_ERROR;
  }

  pubkey = session->current_crypto->server_pubkey;

  md5_update(ctx, ssh_string_data(pubkey), ssh_string_len(pubkey));
  md5_final(h, ctx);

  *hash = h;

  return MD5_DIGEST_LEN;
}
Beispiel #8
0
/** @internal
 * @brief Starts ecdh-sha2-nistp256 key exchange
 */
int ssh_client_ecdh_init(ssh_session session){
  EC_KEY *key=NULL;
  const EC_GROUP *group;
  const EC_POINT *pubkey;
  ssh_string client_pubkey;
  int len;
  int rc;
  bignum_CTX ctx=BN_CTX_new();
  enter_function();
  if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT) < 0) {
    goto error;
  }
  key = EC_KEY_new_by_curve_name(NISTP256);
  group = EC_KEY_get0_group(key);
  EC_KEY_generate_key(key);
  pubkey=EC_KEY_get0_public_key(key);
  len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
      NULL,0,ctx);
  client_pubkey=ssh_string_new(len);

  EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
      ssh_string_data(client_pubkey),len,ctx);
  buffer_add_ssh_string(session->out_buffer,client_pubkey);
  BN_CTX_free(ctx);
  session->next_crypto->ecdh_privkey = key;
  session->next_crypto->ecdh_client_pubkey = client_pubkey;
  rc = packet_send(session);
  leave_function();
  return rc;
error:
  leave_function();
  return SSH_ERROR;
}
Beispiel #9
0
static ssh_string make_ecpoint_string(const EC_GROUP *g,
                                      const EC_POINT *p)
{
    ssh_string s;
    size_t len;

    len = EC_POINT_point2oct(g,
                             p,
                             POINT_CONVERSION_UNCOMPRESSED,
                             NULL,
                             0,
                             NULL);
    if (len == 0) {
        return NULL;
    }

    s = ssh_string_new(len);
    if (s == NULL) {
        return NULL;
    }

    len = EC_POINT_point2oct(g,
                             p,
                             POINT_CONVERSION_UNCOMPRESSED,
                             ssh_string_data(s),
                             ssh_string_len(s),
                             NULL);
    if (len != ssh_string_len(s)) {
        ssh_string_free(s);
        return NULL;
    }

    return s;
}
Beispiel #10
0
/**
 * @brief Convert a public key to a base64 encoded key.
 *
 * @param[in] key       The key to hash
 *
 * @param[out] b64_key  A pointer to store the allocated base64 encoded key. You
 *                      need to free the buffer.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_string_free_char()
 */
int ssh_pki_export_pubkey_base64(const ssh_key key,
                                 char **b64_key)
{
    ssh_string key_blob;
    unsigned char *b64;

    if (key == NULL || b64_key == NULL) {
        return SSH_ERROR;
    }

    key_blob = pki_publickey_to_blob(key);
    if (key_blob == NULL) {
        return SSH_ERROR;
    }

    b64 = bin_to_base64(ssh_string_data(key_blob), ssh_string_len(key_blob));
    ssh_string_free(key_blob);
    if (b64 == NULL) {
        return SSH_ERROR;
    }

    *b64_key = (char *)b64;

    return SSH_OK;
}
Beispiel #11
0
static ssh_string asn1_get_int(ssh_buffer buffer) {
    ssh_string str;
    unsigned char type;
    uint32_t size;

    if (ssh_buffer_get_data(buffer, &type, 1) == 0 || type != ASN1_INTEGER) {
        return NULL;
    }
    size = asn1_get_len(buffer);
    if (size == 0) {
        return NULL;
    }

    str = ssh_string_new(size);
    if (str == NULL) {
        return NULL;
    }

    if (ssh_buffer_get_data(buffer, ssh_string_data(str), size) == 0) {
        ssh_string_free(str);
        return NULL;
    }

    return str;
}
Beispiel #12
0
int pki_pubkey_build_dss(ssh_key key,
                         ssh_string p,
                         ssh_string q,
                         ssh_string g,
                         ssh_string pubkey) {
    gcry_sexp_build(&key->dsa, NULL,
                    "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
                    ssh_string_len(p), ssh_string_data(p),
                    ssh_string_len(q), ssh_string_data(q),
                    ssh_string_len(g), ssh_string_data(g),
                    ssh_string_len(pubkey), ssh_string_data(pubkey));
    if (key->dsa == NULL) {
        return SSH_ERROR;
    }

    return SSH_OK;
}
int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n)
{
    mbedtls_rsa_context *rsa = NULL;
    const mbedtls_pk_info_t *pk_info = NULL;
    int rc;

    key->rsa = malloc(sizeof(mbedtls_pk_context));
    if (key->rsa == NULL) {
        return SSH_ERROR;
    }

    mbedtls_pk_init(key->rsa);
    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
    mbedtls_pk_setup(key->rsa, pk_info);

    rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
    if (rc == 0) {
        goto fail;
    }

    rsa = mbedtls_pk_rsa(*key->rsa);
    rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
                                 ssh_string_len(n));
    if (rc != 0) {
        goto fail;
    }
    rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
                                 ssh_string_len(e));
    if (rc != 0) {
        goto fail;
    }

    rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;

    return SSH_OK;

fail:
    mbedtls_pk_free(key->rsa);
    SAFE_FREE(key->rsa);
    return SSH_ERROR;
}
Beispiel #14
0
/**
 * @internal
 *
 * @brief Import a public key from a ssh string.
 *
 * @param[in]  key_blob The key blob to import as specified in RFC 4253 section
 *                      6.6 "Public Key Algorithms".
 *
 * @param[out] pkey     A pointer where the allocated key can be stored. You
 *                      need to free the memory.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_key_free()
 */
int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
                               ssh_key *pkey) {
    ssh_buffer buffer;
    ssh_string type_s = NULL;
    enum ssh_keytypes_e type;
    int rc;

    if (key_blob == NULL || pkey == NULL) {
        return SSH_ERROR;
    }

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_data(buffer, ssh_string_data(key_blob),
            ssh_string_len(key_blob));
    if (rc < 0) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        goto fail;
    }

    type_s = ssh_buffer_get_ssh_string(buffer);
    if (type_s == NULL) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        goto fail;
    }

    type = ssh_key_type_from_name(ssh_string_get_char(type_s));
    if (type == SSH_KEYTYPE_UNKNOWN) {
        SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
        goto fail;
    }
    ssh_string_free(type_s);

    if (type == SSH_KEYTYPE_RSA_CERT01 ||
        type == SSH_KEYTYPE_DSS_CERT01) {
        rc = pki_import_cert_buffer(buffer, type, pkey);
    } else {
        rc = pki_import_pubkey_buffer(buffer, type, pkey);
    }

    ssh_buffer_free(buffer);

    return rc;
fail:
    ssh_buffer_free(buffer);
    ssh_string_free(type_s);

    return SSH_ERROR;
}
Beispiel #15
0
/** @internal
 * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
 * a SSH_MSG_NEWKEYS
 */
int ssh_client_curve25519_reply(ssh_session_t * session, ssh_buffer_t * packet){
  ssh_string_t * q_s_string = NULL;
  ssh_string_t * pubkey = NULL;
  ssh_string_t * signature = NULL;
  int rc;
  pubkey = buffer_get_ssh_string(packet);
  if (pubkey == NULL){
    ssh_set_error(session,SSH_FATAL, "No public key in packet");
    goto error;
  }
  /* this is the server host key */
  session->next_crypto->server_pubkey = pubkey;
  pubkey = NULL;

  q_s_string = buffer_get_ssh_string(packet);
  if (q_s_string == NULL) {
	  ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
	  goto error;
  }
  if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
	  ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
			  (int)ssh_string_len(q_s_string));
	  ssh_string_free(q_s_string);
	  goto error;
  }
  memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
  ssh_string_free(q_s_string);

  signature = buffer_get_ssh_string(packet);
  if (signature == NULL) {
    ssh_set_error(session, SSH_FATAL, "No signature in packet");
    goto error;
  }
  session->next_crypto->dh_server_signature = signature;
  signature=NULL; /* ownership changed */
  /* TODO: verify signature now instead of waiting for NEWKEYS */
  if (ssh_curve25519_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Cannot build k number");
    goto error;
  }

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

  rc=packet_send(session);
  SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
  return rc;
error:
  return SSH_ERROR;
}
Beispiel #16
0
int ssh_pki_import_signature_blob(const ssh_string sig_blob,
                                  const ssh_key pubkey,
                                  ssh_signature *psig)
{
    ssh_signature sig;
    enum ssh_keytypes_e type;
    ssh_string str;
    ssh_buffer buf;
    int rc;

    if (sig_blob == NULL || psig == NULL) {
        return SSH_ERROR;
    }

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

    rc = ssh_buffer_add_data(buf,
                             ssh_string_data(sig_blob),
                             ssh_string_len(sig_blob));
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    str = ssh_buffer_get_ssh_string(buf);
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    type = ssh_key_type_from_name(ssh_string_get_char(str));
    ssh_string_free(str);

    str = ssh_buffer_get_ssh_string(buf);
    ssh_buffer_free(buf);
    if (str == NULL) {
        return SSH_ERROR;
    }

    sig = pki_signature_from_blob(pubkey, str, type);
    ssh_string_free(str);
    if (sig == NULL) {
        return SSH_ERROR;
    }

    *psig = sig;
    return SSH_OK;
}
Beispiel #17
0
/**
 * @brief Export a private key to a pem file on disk, or OpenSSH format for
 *        keytype ssh-ed25519
 *
 * @param[in]  privkey  The private key to export.
 *
 * @param[in]  passphrase The passphrase to use to encrypt the key with or
 *             NULL. An empty string means no passphrase.
 *
 * @param[in]  auth_fn  An auth function you may want to use or NULL.
 *
 * @param[in]  auth_data Private data passed to the auth function.
 *
 * @param[in]  filename  The path where to store the pem file.
 *
 * @return     SSH_OK on success, SSH_ERROR on error.
 */
int ssh_pki_export_privkey_file(const ssh_key privkey,
                                const char *passphrase,
                                ssh_auth_callback auth_fn,
                                void *auth_data,
                                const char *filename)
{
    ssh_string blob;
    FILE *fp;
    int rc;

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

    fp = fopen(filename, "wb");
    if (fp == NULL) {
        SSH_LOG(SSH_LOG_FUNCTIONS, "Error opening %s: %s",
                filename, strerror(errno));
        return SSH_EOF;
    }

    if (privkey->type == SSH_KEYTYPE_ED25519){
        blob = ssh_pki_openssh_privkey_export(privkey,
                                              passphrase,
                                              auth_fn,
                                              auth_data);
    } else {
        blob = pki_private_key_to_pem(privkey,
                                      passphrase,
                                      auth_fn,
                                      auth_data);
    }
    if (blob == NULL) {
        fclose(fp);
        return -1;
    }

    rc = fwrite(ssh_string_data(blob), ssh_string_len(blob), 1, fp);
    ssh_string_free(blob);
    if (rc != 1 || ferror(fp)) {
        fclose(fp);
        unlink(filename);
        return SSH_ERROR;
    }
    fclose(fp);

    return SSH_OK;
}
Beispiel #18
0
static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s){
    gss_OID ret = malloc(sizeof (gss_OID_desc));
    unsigned char *data = ssh_string_data(oid_s);
    size_t len = ssh_string_len(oid_s);
    if(len > 256 || len <= 2){
        SAFE_FREE(ret);
        return NULL;
    }
    if(data[0] != SSH_OID_TAG || data[1] != len - 2){
        SAFE_FREE(ret);
        return NULL;
    }
    ret->elements = malloc(len - 2);
    memcpy(ret->elements, &data[2], len-2);
    ret->length = len-2;
    return ret;
}
Beispiel #19
0
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) {
    ssh_buffer tmpbuf = NULL;
    ssh_string type_s = NULL;
    char *type_c = NULL;
    int type;

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

    if (buffer_add_data(tmpbuf, ssh_string_data(pubkey_s), ssh_string_len(pubkey_s)) < 0) {
        goto error;
    }

    type_s = buffer_get_ssh_string(tmpbuf);
    if (type_s == NULL) {
        ssh_set_error(session,SSH_FATAL,"Invalid public key format");
        goto error;
    }

    type_c = ssh_string_to_char(type_s);
    ssh_string_free(type_s);
    if (type_c == NULL) {
        goto error;
    }

    type = ssh_type_from_name(type_c);
    SAFE_FREE(type_c);

    switch (type) {
    case SSH_KEYTYPE_DSS:
        return publickey_make_dss(session, tmpbuf);
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
        return publickey_make_rsa(session, tmpbuf, type);
    }

    ssh_set_error(session, SSH_FATAL, "Unknown public key protocol %s",
                  ssh_type_to_char(type));

error:
    ssh_buffer_free(tmpbuf);
    return NULL;
}
Beispiel #20
0
/*
 * Extract an MPI from the given s-expression SEXP named NAME which is
 * encoded using INFORMAT and store it in a newly allocated ssh_string
 * encoded using OUTFORMAT.
 */
ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp,
                                const char *name,
                                enum gcry_mpi_format informat,
                                enum gcry_mpi_format outformat)
{
    gpg_error_t err;
    ssh_string result = NULL;
    gcry_sexp_t fragment = NULL;
    gcry_mpi_t mpi = NULL;
    size_t size;

    fragment = gcry_sexp_find_token(sexp, name, 0);
    if (fragment == NULL) {
        goto fail;
    }

    mpi = gcry_sexp_nth_mpi(fragment, 1, informat);
    if (mpi == NULL) {
        goto fail;
    }

    err = gcry_mpi_print(outformat, NULL, 0, &size, mpi);
    if (err != 0) {
        goto fail;
    }

    result = ssh_string_new(size);
    if (result == NULL) {
        goto fail;
    }

    err = gcry_mpi_print(outformat, ssh_string_data(result), size, NULL, mpi);
    if (err != 0) {
        ssh_string_burn(result);
        ssh_string_free(result);
        result = NULL;
        goto fail;
    }

fail:
    gcry_sexp_release(fragment);
    gcry_mpi_release(mpi);
    return result;
}
Beispiel #21
0
void *sftp_handle(sftp_session sftp, ssh_string handle){
  uint32_t val;

  if (sftp->handles == NULL) {
    return NULL;
  }

  if (ssh_string_len(handle) != sizeof(uint32_t)) {
    return NULL;
  }

  memcpy(&val, ssh_string_data(handle), sizeof(uint32_t));

  if (val > SFTP_HANDLES) {
    return NULL;
  }

  return sftp->handles[val];
}
Beispiel #22
0
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
{
    EC_POINT *p;
    const EC_GROUP *g;
    int ok;

    key->ecdsa_nid = nid;
    key->type_c = pki_key_ecdsa_nid_to_name(nid);

    key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
    if (key->ecdsa == NULL) {
        return -1;
    }

    g = EC_KEY_get0_group(key->ecdsa);

    p = EC_POINT_new(g);
    if (p == NULL) {
        return -1;
    }

    ok = EC_POINT_oct2point(g,
                            p,
                            ssh_string_data(e),
                            ssh_string_len(e),
                            NULL);
    if (!ok) {
        EC_POINT_free(p);
        return -1;
    }

    /* EC_KEY_set_public_key duplicates p */
    ok = EC_KEY_set_public_key(key->ecdsa, p);
    EC_POINT_free(p);
    if (!ok) {
        return -1;
    }

    return 0;
}
Beispiel #23
0
/* TODO : split this function in two so it becomes smaller */
SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,
                                 ssh_public_key pubkey, int needed_type) {
    SIGNATURE *sign = NULL;
    ssh_buffer tmpbuf = NULL;
    ssh_string rs = NULL;
    ssh_string type_s = NULL;
    ssh_string e = NULL;
    char *type_c = NULL;
    int type;
    int len;
    int rsalen;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sig;
#elif defined HAVE_LIBCRYPTO
    DSA_SIG *sig = NULL;
    ssh_string r = NULL;
    ssh_string s = NULL;
#endif

    sign = malloc(sizeof(SIGNATURE));
    if (sign == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        return NULL;
    }
    ZERO_STRUCTP(sign);

    tmpbuf = ssh_buffer_new();
    if (tmpbuf == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        signature_free(sign);
        return NULL;
    }

    if (buffer_add_data(tmpbuf, ssh_string_data(signature), ssh_string_len(signature)) < 0) {
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    type_s = buffer_get_ssh_string(tmpbuf);
    if (type_s == NULL) {
        ssh_set_error(session, SSH_FATAL, "Invalid signature packet");
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    type_c = ssh_string_to_char(type_s);
    ssh_string_free(type_s);
    if (type_c == NULL) {
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    type = ssh_type_from_name(type_c);
    SAFE_FREE(type_c);

    if (needed_type != type) {
        ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s",
                      ssh_type_to_char(type));
        signature_free(sign);
        ssh_buffer_free(tmpbuf);
        return NULL;
    }

    switch(needed_type) {
    case SSH_KEYTYPE_DSS:
        rs = buffer_get_ssh_string(tmpbuf);
        ssh_buffer_free(tmpbuf);

        /* 40 is the dual signature blob len. */
        if (rs == NULL || ssh_string_len(rs) != 40) {
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }

        /* we make use of strings (because we have all-made functions to convert
         * them to bignums (ou pas ;) */
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
                            20 ,ssh_string_data(rs), 20,(unsigned char *)ssh_string_data(rs) + 20)) {
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        r = ssh_string_new(20);
        s = ssh_string_new(20);
        if (r == NULL || s == NULL) {
            ssh_string_free(r);
            ssh_string_free(s);
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }

        ssh_string_fill(r, ssh_string_data(rs), 20);
        ssh_string_fill(s, (char *)ssh_string_data(rs) + 20, 20);

        sig = DSA_SIG_new();
        if (sig == NULL) {
            ssh_string_free(r);
            ssh_string_free(s);
            ssh_string_free(rs);
            signature_free(sign);
            return NULL;
        }
        sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */
        sig->s = make_string_bn(s);
        ssh_string_free(r);
        ssh_string_free(s);

        if (sig->r == NULL || sig->s == NULL) {
            ssh_string_free(rs);
            DSA_SIG_free(sig);
            signature_free(sign);
            return NULL;
        }
#endif

#ifdef DEBUG_CRYPTO
        ssh_print_hexa("r", ssh_string_data(rs), 20);
        ssh_print_hexa("s", (const unsigned char *)ssh_string_data(rs) + 20, 20);
#endif
        ssh_string_free(rs);

        sign->type = SSH_KEYTYPE_DSS;
        sign->dsa_sign = sig;

        return sign;
    case SSH_KEYTYPE_RSA:
        e = buffer_get_ssh_string(tmpbuf);
        ssh_buffer_free(tmpbuf);
        if (e == NULL) {
            signature_free(sign);
            return NULL;
        }
        len = ssh_string_len(e);
#ifdef HAVE_LIBGCRYPT
        rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8;
#elif defined HAVE_LIBCRYPTO
        rsalen = RSA_size(pubkey->rsa_pub);
#endif
        if (len > rsalen) {
            ssh_string_free(e);
            signature_free(sign);
            ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d",
                          len, rsalen);
            return NULL;
        }

        if (len < rsalen) {
            ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d",
                    len, rsalen);
        }
        sign->type = SSH_KEYTYPE_RSA;
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
                            ssh_string_len(e), ssh_string_data(e))) {
            signature_free(sign);
            ssh_string_free(e);
            return NULL;
        }

        sign->rsa_sign = sig;
#elif defined HAVE_LIBCRYPTO
        sign->rsa_sign = e;
#endif

#ifdef DEBUG_CRYPTO
        ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
        ssh_print_hexa("RSA signature", ssh_string_data(e), len);
#endif

#ifdef HAVE_LIBGCRYPT
        ssh_string_free(e);
#endif

        return sign;
    default:
        return NULL;
    }

    return NULL;
}
Beispiel #24
0
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) {
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string pubkey = NULL;
    ssh_public_key key = NULL;

    key = malloc(sizeof(struct ssh_public_key_struct));
    if (key == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    ZERO_STRUCTP(key);

    key->type = SSH_KEYTYPE_DSS;
    key->type_c = ssh_type_to_char(key->type);

    p = buffer_get_ssh_string(buffer);
    q = buffer_get_ssh_string(buffer);
    g = buffer_get_ssh_string(buffer);
    pubkey = buffer_get_ssh_string(buffer);

    ssh_buffer_free(buffer); /* we don't need it anymore */

    if (p == NULL || q == NULL || g == NULL || pubkey == NULL) {
        ssh_set_error(session, SSH_FATAL, "Invalid DSA public key");
        goto error;
    }

#ifdef HAVE_LIBGCRYPT
    gcry_sexp_build(&key->dsa_pub, NULL,
                    "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
                    ssh_string_len(p), ssh_string_data(p),
                    ssh_string_len(q), ssh_string_data(q),
                    ssh_string_len(g), ssh_string_data(g),
                    ssh_string_len(pubkey), ssh_string_data(pubkey));
    if (key->dsa_pub == NULL) {
        goto error;
    }
#elif defined HAVE_LIBCRYPTO

    key->dsa_pub = DSA_new();
    if (key->dsa_pub == NULL) {
        goto error;
    }
    key->dsa_pub->p = make_string_bn(p);
    key->dsa_pub->q = make_string_bn(q);
    key->dsa_pub->g = make_string_bn(g);
    key->dsa_pub->pub_key = make_string_bn(pubkey);
    if (key->dsa_pub->p == NULL ||
            key->dsa_pub->q == NULL ||
            key->dsa_pub->g == NULL ||
            key->dsa_pub->pub_key == NULL) {
        goto error;
    }
#endif /* HAVE_LIBCRYPTO */

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
    ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
    ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
#endif

    ssh_string_burn(p);
    ssh_string_free(p);
    ssh_string_burn(q);
    ssh_string_free(q);
    ssh_string_burn(g);
    ssh_string_free(g);
    ssh_string_burn(pubkey);
    ssh_string_free(pubkey);

    return key;
error:
    ssh_string_burn(p);
    ssh_string_free(p);
    ssh_string_burn(q);
    ssh_string_free(q);
    ssh_string_burn(g);
    ssh_string_free(g);
    ssh_string_burn(pubkey);
    ssh_string_free(pubkey);
    publickey_free(key);

    return NULL;
}
Beispiel #25
0
/* Signature decoding functions */
ssh_string signature_to_string(SIGNATURE *sign) {
    unsigned char buffer[40] = {0};
    ssh_buffer tmpbuf = NULL;
    ssh_string str = NULL;
    ssh_string tmp = NULL;
    ssh_string rs = NULL;
    int rc = -1;
#ifdef HAVE_LIBGCRYPT
    const char *r = NULL;
    const char *s = NULL;
    gcry_sexp_t sexp;
    size_t size = 0;
#elif defined HAVE_LIBCRYPTO
    ssh_string r = NULL;
    ssh_string s = NULL;
#endif

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

    tmp = ssh_string_from_char(ssh_type_to_char(sign->type));
    if (tmp == NULL) {
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    if (buffer_add_ssh_string(tmpbuf, tmp) < 0) {
        ssh_buffer_free(tmpbuf);
        ssh_string_free(tmp);
        return NULL;
    }
    ssh_string_free(tmp);

    switch(sign->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(sign->dsa_sign, "r", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        r = gcry_sexp_nth_data(sexp, 1, &size);
        if (*r == 0) {      /* libgcrypt put 0 when first bit is set */
            size--;
            r++;
        }
        memcpy(buffer, r + size - 20, 20);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(sign->dsa_sign, "s", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = gcry_sexp_nth_data(sexp,1,&size);
        if (*s == 0) {
            size--;
            s++;
        }
        memcpy(buffer+ 20, s + size - 20, 20);
        gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO
        r = make_bignum_string(sign->dsa_sign->r);
        if (r == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = make_bignum_string(sign->dsa_sign->s);
        if (s == NULL) {
            ssh_buffer_free(tmpbuf);
            ssh_string_free(r);
            return NULL;
        }

        memcpy(buffer, (char *)ssh_string_data(r) + ssh_string_len(r) - 20, 20);
        memcpy(buffer + 20, (char *)ssh_string_data(s) + ssh_string_len(s) - 20, 20);

        ssh_string_free(r);
        ssh_string_free(s);
#endif /* HAVE_LIBCRYPTO */
        rs = ssh_string_new(40);
        if (rs == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        ssh_string_fill(rs, buffer, 40);
        rc = buffer_add_ssh_string(tmpbuf, rs);
        ssh_string_free(rs);
        if (rc < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(sign->rsa_sign, "s", 0);
        if (sexp == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
        s = gcry_sexp_nth_data(sexp,1,&size);
        if (*s == 0) {
            size--;
            s++;
        }
        rs = ssh_string_new(size);
        if (rs == NULL) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }

        ssh_string_fill(rs, (char *) s, size);
        rc = buffer_add_ssh_string(tmpbuf, rs);
        gcry_sexp_release(sexp);
        ssh_string_free(rs);
        if (rc < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        if (buffer_add_ssh_string(tmpbuf,sign->rsa_sign) < 0) {
            ssh_buffer_free(tmpbuf);
            return NULL;
        }
#endif
        break;
    }

    str = ssh_string_new(buffer_get_rest_len(tmpbuf));
    if (str == NULL) {
        ssh_buffer_free(tmpbuf);
        return NULL;
    }
    ssh_string_fill(str, buffer_get_rest(tmpbuf), buffer_get_rest_len(tmpbuf));
    ssh_buffer_free(tmpbuf);

    return str;
}
Beispiel #26
0
/**
 * @brief Make a public_key object out of a private_key object.
 *
 * @param[in]  prv      The private key to generate the public key.
 *
 * @returns             The generated public key, NULL on error.
 *
 * @see publickey_to_string()
 */
ssh_public_key publickey_from_privatekey(ssh_private_key prv) {
    ssh_public_key key = NULL;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sexp;
    const char *tmp = NULL;
    size_t size;
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string y = NULL;
    ssh_string e = NULL;
    ssh_string n = NULL;
#endif /* HAVE_LIBGCRYPT */

    key = malloc(sizeof(struct ssh_public_key_struct));
    if (key == NULL) {
        return NULL;
    }
    ZERO_STRUCTP(key);
    key->type = prv->type;
    switch(key->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        p = ssh_string_new(size);
        if (p == NULL) {
            goto error;
        }
        ssh_string_fill(p,(char *) tmp, size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        q = ssh_string_new(size);
        if (q == NULL) {
            goto error;
        }
        ssh_string_fill(q,(char *) tmp,size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        g = ssh_string_new(size);
        if (g == NULL) {
            goto error;
        }
        ssh_string_fill(g,(char *) tmp,size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp,1,&size);
        y = ssh_string_new(size);
        if (y == NULL) {
            goto error;
        }
        ssh_string_fill(y,(char *) tmp,size);
        gcry_sexp_release(sexp);

        gcry_sexp_build(&key->dsa_pub, NULL,
                        "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",
                        ssh_string_len(p), ssh_string_data(p),
                        ssh_string_len(q), ssh_string_data(q),
                        ssh_string_len(g), ssh_string_data(g),
                        ssh_string_len(y), ssh_string_data(y));

        ssh_string_burn(p);
        ssh_string_free(p);
        ssh_string_burn(q);
        ssh_string_free(q);
        ssh_string_burn(g);
        ssh_string_free(g);
        ssh_string_burn(y);
        ssh_string_free(y);
#elif defined HAVE_LIBCRYPTO
        key->dsa_pub = DSA_new();
        if (key->dsa_pub == NULL) {
            goto error;
        }
        key->dsa_pub->p = BN_dup(prv->dsa_priv->p);
        key->dsa_pub->q = BN_dup(prv->dsa_priv->q);
        key->dsa_pub->g = BN_dup(prv->dsa_priv->g);
        key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key);
        if (key->dsa_pub->p == NULL ||
                key->dsa_pub->q == NULL ||
                key->dsa_pub->g == NULL ||
                key->dsa_pub->pub_key == NULL) {
            goto error;
        }
#endif /* HAVE_LIBCRYPTO */
        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
        sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        n = ssh_string_new(size);
        if (n == NULL) {
            goto error;
        }
        ssh_string_fill(n, (char *) tmp, size);
        gcry_sexp_release(sexp);

        sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0);
        if (sexp == NULL) {
            goto error;
        }
        tmp = gcry_sexp_nth_data(sexp, 1, &size);
        e = ssh_string_new(size);
        if (e == NULL) {
            goto error;
        }
        ssh_string_fill(e, (char *) tmp, size);
        gcry_sexp_release(sexp);

        gcry_sexp_build(&key->rsa_pub, NULL,
                        "(public-key(rsa(n %b)(e %b)))",
                        ssh_string_len(n), ssh_string_data(n),
                        ssh_string_len(e), ssh_string_data(e));
        if (key->rsa_pub == NULL) {
            goto error;
        }

        ssh_string_burn(e);
        ssh_string_free(e);
        ssh_string_burn(n);
        ssh_string_free(n);
#elif defined HAVE_LIBCRYPTO
        key->rsa_pub = RSA_new();
        if (key->rsa_pub == NULL) {
            goto error;
        }
        key->rsa_pub->e = BN_dup(prv->rsa_priv->e);
        key->rsa_pub->n = BN_dup(prv->rsa_priv->n);
        if (key->rsa_pub->e == NULL ||
                key->rsa_pub->n == NULL) {
            goto error;
        }
#endif
        break;
    default:
        publickey_free(key);
        return NULL;
    }
    key->type_c = ssh_type_to_char(prv->type);

    return key;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
    ssh_string_burn(p);
    ssh_string_free(p);
    ssh_string_burn(q);
    ssh_string_free(q);
    ssh_string_burn(g);
    ssh_string_free(g);
    ssh_string_burn(y);
    ssh_string_free(y);

    ssh_string_burn(e);
    ssh_string_free(e);
    ssh_string_burn(n);
    ssh_string_free(n);
#endif
    publickey_free(key);

    return NULL;
}
Beispiel #27
0
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer,
                                  int type) {
    ssh_string e = NULL;
    ssh_string n = NULL;
    ssh_public_key key = NULL;

    key = malloc(sizeof(struct ssh_public_key_struct));
    if (key == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    ZERO_STRUCTP(key);

    key->type = type;
    key->type_c = ssh_type_to_char(key->type);

    e = buffer_get_ssh_string(buffer);
    n = buffer_get_ssh_string(buffer);

    ssh_buffer_free(buffer); /* we don't need it anymore */

    if(e == NULL || n == NULL) {
        ssh_set_error(session, SSH_FATAL, "Invalid RSA public key");
        goto error;
    }
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_build(&key->rsa_pub, NULL,
                    "(public-key(rsa(n %b)(e %b)))",
                    ssh_string_len(n), ssh_string_data(n),
                    ssh_string_len(e),ssh_string_data(e));
    if (key->rsa_pub == NULL) {
        goto error;
    }
#elif HAVE_LIBCRYPTO
    key->rsa_pub = RSA_new();
    if (key->rsa_pub == NULL) {
        goto error;
    }

    key->rsa_pub->e = make_string_bn(e);
    key->rsa_pub->n = make_string_bn(n);
    if (key->rsa_pub->e == NULL ||
            key->rsa_pub->n == NULL) {
        goto error;
    }
#endif

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
    ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
#endif

    ssh_string_burn(e);
    ssh_string_free(e);
    ssh_string_burn(n);
    ssh_string_free(n);

    return key;
error:
    ssh_string_burn(e);
    ssh_string_free(e);
    ssh_string_burn(n);
    ssh_string_free(n);
    publickey_free(key);

    return NULL;
}
Beispiel #28
0
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key) {
    ssh_string str = NULL;
    size_t len = ssh_string_len(data);
    size_t size = 0;
#ifdef HAVE_LIBGCRYPT
    const char *tmp = NULL;
    gcry_sexp_t ret_sexp;
    gcry_sexp_t data_sexp;

    if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))",
                        len, ssh_string_data(data))) {
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        return NULL;
    }
    if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) {
        gcry_sexp_release(data_sexp);
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        return NULL;
    }

    gcry_sexp_release(data_sexp);

    data_sexp = gcry_sexp_find_token(ret_sexp, "a", 0);
    if (data_sexp == NULL) {
        ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error");
        gcry_sexp_release(ret_sexp);
        return NULL;
    }
    tmp = gcry_sexp_nth_data(data_sexp, 1, &size);
    if (*tmp == 0) {
        size--;
        tmp++;
    }

    str = ssh_string_new(size);
    if (str == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        gcry_sexp_release(data_sexp);
        gcry_sexp_release(ret_sexp);
        return NULL;
    }
    ssh_string_fill(str, tmp, size);

    gcry_sexp_release(data_sexp);
    gcry_sexp_release(ret_sexp);
#elif defined HAVE_LIBCRYPTO
    size = RSA_size(key->rsa_pub);

    str = ssh_string_new(size);
    if (str == NULL) {
        ssh_set_error(session, SSH_FATAL, "Not enough space");
        return NULL;
    }

    if (RSA_public_encrypt(len, ssh_string_data(data), ssh_string_data(str), key->rsa_pub,
                           RSA_PKCS1_PADDING) < 0) {
        ssh_string_free(str);
        return NULL;
    }
#endif

    return str;
}
Beispiel #29
0
static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_callback cb,
                                    void *userdata, const char *desc) {
    const unsigned char *data;
    ssh_buffer buffer = NULL;
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string y = NULL;
    ssh_string x = NULL;
    ssh_string v = NULL;
    int rc = 1;

    buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_DSS, cb, userdata, desc);
    if (buffer == NULL) {
        return 0;
    }

    if (!asn1_check_sequence(buffer)) {
        ssh_buffer_free(buffer);
        return 0;
    }

    v = asn1_get_int(buffer);
    if (v == NULL) {
        ssh_buffer_free(buffer);
        return 0;
    }

    data = ssh_string_data(v);
    if (ssh_string_len(v) != 1 || data[0] != 0) {
        ssh_buffer_free(buffer);
        return 0;
    }

    p = asn1_get_int(buffer);
    q = asn1_get_int(buffer);
    g = asn1_get_int(buffer);
    y = asn1_get_int(buffer);
    x = asn1_get_int(buffer);
    ssh_buffer_free(buffer);

    if (p == NULL || q == NULL || g == NULL || y == NULL || x == NULL) {
        rc = 0;
        goto error;
    }

    if (gcry_sexp_build(r, NULL,
                        "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",
                        ssh_string_len(p), ssh_string_data(p),
                        ssh_string_len(q), ssh_string_data(q),
                        ssh_string_len(g), ssh_string_data(g),
                        ssh_string_len(y), ssh_string_data(y),
                        ssh_string_len(x), ssh_string_data(x))) {
        rc = 0;
    }

error:
    ssh_string_free(p);
    ssh_string_free(q);
    ssh_string_free(g);
    ssh_string_free(y);
    ssh_string_free(x);
    ssh_string_free(v);

    return rc;
}
Beispiel #30
0
static int pki_import_pubkey_buffer(ssh_buffer buffer,
                                    enum ssh_keytypes_e type,
                                    ssh_key *pkey) {
    ssh_key key;
    int rc;

    key = ssh_key_new();
    if (key == NULL) {
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PUBLIC;

    switch (type) {
        case SSH_KEYTYPE_DSS:
            {
                ssh_string p;
                ssh_string q;
                ssh_string g;
                ssh_string pubkey;

                p = ssh_buffer_get_ssh_string(buffer);
                if (p == NULL) {
                    goto fail;
                }
                q = ssh_buffer_get_ssh_string(buffer);
                if (q == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);

                    goto fail;
                }
                g = ssh_buffer_get_ssh_string(buffer);
                if (g == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);

                    goto fail;
                }
                pubkey = ssh_buffer_get_ssh_string(buffer);
                if (pubkey == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);
                    ssh_string_burn(g);
                    ssh_string_free(g);

                    goto fail;
                }

                rc = pki_pubkey_build_dss(key, p, q, g, pubkey);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
                ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
                ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
#endif
                ssh_string_burn(p);
                ssh_string_free(p);
                ssh_string_burn(q);
                ssh_string_free(q);
                ssh_string_burn(g);
                ssh_string_free(g);
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            {
                ssh_string e;
                ssh_string n;

                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }
                n = ssh_buffer_get_ssh_string(buffer);
                if (n == NULL) {
                    ssh_string_burn(e);
                    ssh_string_free(e);

                    goto fail;
                }

                rc = pki_pubkey_build_rsa(key, e, n);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
                ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
#endif
                ssh_string_burn(e);
                ssh_string_free(e);
                ssh_string_burn(n);
                ssh_string_free(n);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
            {
                ssh_string e;
                ssh_string i;
                int nid;

                i = ssh_buffer_get_ssh_string(buffer);
                if (i == NULL) {
                    goto fail;
                }
                nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
                ssh_string_free(i);
                if (nid == -1) {
                    goto fail;
                }


                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }

                rc = pki_pubkey_build_ecdsa(key, nid, e);
                ssh_string_burn(e);
                ssh_string_free(e);
                if (rc < 0) {
                    goto fail;
                }

                /* Update key type */
                key->type_c = ssh_pki_key_ecdsa_name(key);
            }
            break;
#endif
        case SSH_KEYTYPE_ED25519:
        {
            ssh_string pubkey = ssh_buffer_get_ssh_string(buffer);
            if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
                SSH_LOG(SSH_LOG_WARN, "Invalid public key length");
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            key->ed25519_pubkey = malloc(ED25519_PK_LEN);
            if (key->ed25519_pubkey == NULL) {
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
            ssh_string_burn(pubkey);
            ssh_string_free(pubkey);
        }
        break;
        case SSH_KEYTYPE_DSS_CERT01:
        case SSH_KEYTYPE_RSA_CERT01:
        case SSH_KEYTYPE_UNKNOWN:
        default:
            SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type);
            goto fail;
    }

    *pkey = key;
    return SSH_OK;
fail:
    ssh_key_free(key);

    return SSH_ERROR;
}