Example #1
0
/* 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 (rsa == NULL) {
      goto error;
  }

  if (ssh_buffer_add_ssh_string(buffer, rsa) < 0) {
    goto error;
  }
  if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
    goto error;
  }
  if (ssh_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(buffer), ssh_buffer_get_len(buffer));
error:
  ssh_buffer_free(buffer);
  ssh_string_free(rsa);

  return ret;
}
Example #2
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;
}
Example #3
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;
}
Example #4
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;
}
Example #5
0
static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey,
    ssh_public_key hostkey, int slen, int hlen) {
  unsigned char buffer[32] = {0};
  int i;
  ssh_string data1 = NULL;
  ssh_string data2 = NULL;

  /* first, generate a session key */
  ssh_get_random(session->next_crypto->encryptkey, 32, 1);
  memcpy(buffer, session->next_crypto->encryptkey, 32);
  memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey, 32);

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("session key",buffer,32);
#endif

  /* xor session key with session_id */
  for (i = 0; i < 16; i++) {
    buffer[i] ^= session->next_crypto->session_id[i];
  }
  data1 = ssh_string_new(32);
  if (data1 == NULL) {
    return NULL;
  }
  ssh_string_fill(data1, buffer, 32);
  if (ABS(hlen - slen) < 128){
    ssh_log(session, SSH_LOG_FUNCTIONS,
        "Difference between server modulus and host modulus is only %d. "
        "It's illegal and may not work",
        ABS(hlen - slen));
  }

  if (modulus_smaller(srvkey, hostkey)) {
    data2 = ssh_encrypt_rsa1(session, data1, srvkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, hostkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  } else {
    data2 = ssh_encrypt_rsa1(session, data1, hostkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, srvkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  }

  return data1;
}
Example #6
0
ssh_string ssh_make_bignum_string(bignum num) {
  ssh_string ptr = NULL;
  int pad = 0;
  unsigned int len = bignum_num_bytes(num);
  unsigned int bits = bignum_num_bits(num);

  if (len == 0) {
      return NULL;
  }

  /* If the first bit is set we have a negative number */
  if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
    pad++;
  }

#ifdef DEBUG_CRYPTO
  fprintf(stderr, "%d bits, %d bytes, %d padding\n", bits, len, pad);
#endif /* DEBUG_CRYPTO */

  ptr = ssh_string_new(len + pad);
  if (ptr == NULL) {
    return NULL;
  }

  /* We have a negative number so we need a leading zero */
  if (pad) {
    ptr->data[0] = 0;
  }

  bignum_bn2bin(num, len, ptr->data + pad);

  return ptr;
}
Example #7
0
File: keys.c Project: rofl0r/libssh
/*
 * Maybe the missing function from libcrypto
 *
 * I think now, maybe it's a bad idea to name it has it should have be
 * named in libcrypto
 */
ssh_string RSA_do_sign(const unsigned char *payload, int len, RSA *privkey) {
    ssh_string sign = NULL;
    unsigned char *buffer = NULL;
    unsigned int size;

    buffer = malloc(RSA_size(privkey));
    if (buffer == NULL) {
        return NULL;
    }

    if (RSA_sign(NID_sha1, payload, len, buffer, &size, privkey) == 0) {
        SAFE_FREE(buffer);
        return NULL;
    }

    sign = ssh_string_new(size);
    if (sign == NULL) {
        SAFE_FREE(buffer);
        return NULL;
    }

    ssh_string_fill(sign, buffer, size);
    SAFE_FREE(buffer);

    return sign;
}
Example #8
0
File: keys.c Project: rofl0r/libssh
/*
 * This function concats in a buffer the values needed to do a signature
 * verification. */
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service) {
    /*
         The value of 'signature' is a signature by the corresponding private
       key over the following data, in the following order:

          string    session identifier
          byte      SSH_MSG_USERAUTH_REQUEST
          string    user name
          string    service name
          string    "publickey"
          boolean   TRUE
          string    public key algorithm name
          string    public key to be used for authentication
    */
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
                                           session->next_crypto;
    ssh_buffer buffer = NULL;
    ssh_string session_id = NULL;
    uint8_t type = SSH2_MSG_USERAUTH_REQUEST;
    ssh_string username = ssh_string_from_char(msg->auth_request.username);
    ssh_string servicename = ssh_string_from_char(service);
    ssh_string method = ssh_string_from_char("publickey");
    uint8_t has_sign = 1;
    ssh_string algo = ssh_string_from_char(msg->auth_request.public_key->type_c);
    ssh_string publickey = publickey_to_string(msg->auth_request.public_key);

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        goto error;
    }
    session_id = ssh_string_new(SHA_DIGEST_LEN);
    if (session_id == NULL) {
        ssh_buffer_free(buffer);
        buffer = NULL;
        goto error;
    }
    ssh_string_fill(session_id, crypto->session_id, SHA_DIGEST_LEN);

    if(buffer_add_ssh_string(buffer, session_id) < 0 ||
            buffer_add_u8(buffer, type) < 0 ||
            buffer_add_ssh_string(buffer, username) < 0 ||
            buffer_add_ssh_string(buffer, servicename) < 0 ||
            buffer_add_ssh_string(buffer, method) < 0 ||
            buffer_add_u8(buffer, has_sign) < 0 ||
            buffer_add_ssh_string(buffer, algo) < 0 ||
            buffer_add_ssh_string(buffer, publickey) < 0) {
        ssh_buffer_free(buffer);
        buffer = NULL;
        goto error;
    }

error:
    if(session_id) ssh_string_free(session_id);
    if(username) ssh_string_free(username);
    if(servicename) ssh_string_free(servicename);
    if(method) ssh_string_free(method);
    if(algo) ssh_string_free(algo);
    if(publickey) ssh_string_free(publickey);
    return buffer;
}
Example #9
0
/** @internal
 * @brief Starts [email protected] key exchange
 */
int ssh_client_curve25519_init(ssh_session_t * session){
  ssh_string_t * client_pubkey;
  int rc;

  rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
  if (rc < 0) {
      return SSH_ERROR;
  }

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

  crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
		  session->next_crypto->curve25519_privkey);
  client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE);
  if (client_pubkey == NULL) {
      return SSH_ERROR;
  }
  ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey,
		  CURVE25519_PUBKEY_SIZE);
  rc = buffer_add_ssh_string(session->out_buffer,client_pubkey);
  ssh_string_free(client_pubkey);
  if (rc < 0) {
      return SSH_ERROR;
  }

  rc = packet_send(session);

  return rc;
}
Example #10
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;
}
Example #11
0
File: pki.c Project: codinn/libssh
int ssh_pki_export_signature_blob(const ssh_signature sig,
                                  ssh_string *sig_blob)
{
    ssh_buffer buf = NULL;
    ssh_string str;
    int rc;

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

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

    str = ssh_string_from_char(sig->type_c);
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_ssh_string(buf, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

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

    rc = ssh_buffer_add_ssh_string(buf, str);
    ssh_string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

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

    ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
    ssh_buffer_free(buf);

    *sig_blob = str;

    return SSH_OK;
}
Example #12
0
File: pki.c Project: codinn/libssh
ssh_string ssh_pki_do_sign_agent(ssh_session session,
                                 struct ssh_buffer_struct *buf,
                                 const ssh_key pubkey) {
    struct ssh_crypto_struct *crypto;
    ssh_string session_id;
    ssh_string sig_blob;
    ssh_buffer sig_buf;
    int rc;

    if (session->current_crypto) {
        crypto = session->current_crypto;
    } else {
        crypto = session->next_crypto;
    }

    /* prepend session identifier */
    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);

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

    rc = ssh_buffer_add_ssh_string(sig_buf, session_id);
    if (rc < 0) {
        ssh_string_free(session_id);
        ssh_buffer_free(sig_buf);
        return NULL;
    }
    ssh_string_free(session_id);

    /* append out buffer */
    if (ssh_buffer_add_buffer(sig_buf, buf) < 0) {
        ssh_buffer_free(sig_buf);
        return NULL;
    }

    /* create signature */
    sig_blob = ssh_agent_sign_data(session, pubkey, sig_buf);

    ssh_buffer_free(sig_buf);

    return sig_blob;
}
Example #13
0
File: keys.c Project: rofl0r/libssh
ssh_string ssh_do_sign_with_agent(ssh_session session,
                                  struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey) {
    struct ssh_buffer_struct *sigbuf = NULL;
    struct ssh_string_struct *signature = NULL;
    struct ssh_string_struct *session_id = NULL;
    struct ssh_crypto_struct *crypto = NULL;

    if (session->current_crypto) {
        crypto = session->current_crypto;
    } else {
        crypto = session->next_crypto;
    }

    /* prepend session identifier */
    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);

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

    if (buffer_add_ssh_string(sigbuf, session_id) < 0) {
        ssh_buffer_free(sigbuf);
        ssh_string_free(session_id);
        return NULL;
    }
    ssh_string_free(session_id);

    /* append out buffer */
    if (buffer_add_buffer(sigbuf, buf) < 0) {
        ssh_buffer_free(sigbuf);
        return NULL;
    }

    /* create signature */
    signature = agent_sign_data(session, sigbuf, publickey);

    ssh_buffer_free(sigbuf);

    return signature;
}
Example #14
0
File: pki.c Project: rofl0r/libssh
/*
 * This function signs the session id (known as H) as a string then
 * the content of sigbuf */
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
    ssh_key privatekey) {
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
        session->next_crypto;
    unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
    ssh_string session_str = NULL;
    ssh_string signature = NULL;
    struct signature_struct *sign = NULL;
    SHACTX ctx = NULL;

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

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

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

    sha1_update(ctx, session_str, ssh_string_len(session_str) + 4);
    ssh_string_free(session_str);
    sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
    sha1_final(hash + 1,ctx);
    hash[0] = 0;

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN);
#endif

    sign = pki_do_sign(privatekey, hash);
    if (sign == NULL) {
        return NULL;
    }

    signature = signature_to_string(sign);
    signature_free(sign);

    return signature;
}
Example #15
0
File: keys.c Project: rofl0r/libssh
/**
 * @brief Convert a public_key object into a a SSH string.
 *
 * @param[in]  key      The public key to convert.
 *
 * @returns             An allocated SSH String containing the public key, NULL
 *                      on error.
 *
 * @see string_free()
 */
ssh_string publickey_to_string(ssh_public_key key) {
    ssh_string type = NULL;
    ssh_string ret = NULL;
    ssh_buffer buf = NULL;

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

    type = ssh_string_from_char(key->type_c);
    if (type == NULL) {
        goto error;
    }

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

    switch (key->type) {
    case SSH_KEYTYPE_DSS:
        if (dsa_public_to_string(key->dsa_pub, buf) < 0) {
            goto error;
        }
        break;
    case SSH_KEYTYPE_RSA:
    case SSH_KEYTYPE_RSA1:
        if (rsa_public_to_string(key->rsa_pub, buf) < 0) {
            goto error;
        }
        break;
    }

    ret = ssh_string_new(buffer_get_rest_len(buf));
    if (ret == NULL) {
        goto error;
    }

    ssh_string_fill(ret, buffer_get_rest(buf), buffer_get_rest_len(buf));
error:
    ssh_buffer_free(buf);
    if(type != NULL)
        ssh_string_free(type);

    return ret;
}
Example #16
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;
}
Example #17
0
/**
 * @brief launches a gssapi-with-mic auth request
 * @returns SSH_AUTH_ERROR:   A serious error happened\n
 *          SSH_AUTH_DENIED:  Authentication failed : use another method\n
 *          SSH_AUTH_AGAIN:   In nonblocking mode, you've got to call this again
 *                            later.
 */
int ssh_gssapi_auth_mic(ssh_session session){
    int i;
    gss_OID_set selected; /* oid selected for authentication */
    ssh_string *oids;
    int rc;
    int n_oids = 0;

    if (ssh_gssapi_init(session) == SSH_ERROR)
        return SSH_AUTH_ERROR;


    SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi to host %s with user %s",
            session->opts.host, session->opts.username);
    rc = ssh_gssapi_match(session,session->opts.host, session->opts.username, &selected, 0);
    if (rc == SSH_ERROR)
        return SSH_AUTH_DENIED;

    n_oids = selected->count;
    SSH_LOG(SSH_LOG_PROTOCOL, "Sending %d oids", n_oids);

    oids = calloc(n_oids, sizeof(ssh_string));

    for (i=0; i<n_oids; ++i){
        oids[i] = ssh_string_new(selected->elements[i].length + 2);
        ((unsigned char *)oids[i]->data)[0] = SSH_OID_TAG;
        ((unsigned char *)oids[i]->data)[1] = selected->elements[i].length;
        memcpy((unsigned char *)oids[i]->data + 2, selected->elements[i].elements,
                selected->elements[i].length);
    }

    rc = ssh_gssapi_send_auth_mic(session, oids, n_oids);
    for (i = 0; i < n_oids; i++) {
        ssh_string_free(oids[i]);
    }
    free(oids);
    if (rc != SSH_ERROR) {
        return SSH_AUTH_AGAIN;
    }

    return SSH_AUTH_ERROR;
}
Example #18
0
File: keys.c Project: rofl0r/libssh
/* 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;
}
Example #19
0
File: keys.c Project: rofl0r/libssh
/* 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;
}
Example #20
0
File: keys.c Project: rofl0r/libssh
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO
static int rsa_public_to_string(RSA *key, ssh_buffer buffer) {
#endif

    ssh_string e = NULL;
    ssh_string n = NULL;

    int rc = -1;

#ifdef HAVE_LIBGCRYPT
    const char *tmp;
    size_t size;
    gcry_sexp_t sexp;

    sexp = gcry_sexp_find_token(key, "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(key, "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);

#elif defined HAVE_LIBCRYPTO
    e = make_bignum_string(key->e);
    n = make_bignum_string(key->n);
    if (e == NULL || n == NULL) {
        goto error;
    }
#endif

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

    rc = 0;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
#endif

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

    return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
Example #21
0
/**
 * @brief launches a gssapi-with-mic auth request
 * @returns SSH_AUTH_ERROR:   A serious error happened\n
 *          SSH_AUTH_DENIED:  Authentication failed : use another method\n
 *          SSH_AUTH_AGAIN:   In nonblocking mode, you've got to call this again
 *                            later.
 */
int ssh_gssapi_auth_mic(ssh_session session){
    int i;
    gss_OID_set selected; /* oid selected for authentication */
    ssh_string *oids;
    int rc;
    int n_oids = 0;
    OM_uint32 maj_stat, min_stat;
    char name_buf[256];
    gss_buffer_desc hostname;
    const char *gss_host = session->opts.host;

    rc = ssh_gssapi_init(session);
    if (rc == SSH_ERROR) {
        return SSH_AUTH_ERROR;
    }

    if (session->opts.gss_server_identity != NULL) {
        gss_host = session->opts.gss_server_identity;
    }
    /* import target host name */
    snprintf(name_buf, sizeof(name_buf), "host@%s", gss_host);

    hostname.value = name_buf;
    hostname.length = strlen(name_buf) + 1;
    maj_stat = gss_import_name(&min_stat, &hostname,
                               (gss_OID)GSS_C_NT_HOSTBASED_SERVICE,
                               &session->gssapi->client.server_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat);
        return SSH_PACKET_USED;
    }

    /* copy username */
    session->gssapi->user = strdup(session->opts.username);
    if (session->gssapi->user == NULL) {
        ssh_set_error_oom(session);
        return SSH_AUTH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi to host %s with user %s",
            session->opts.host, session->gssapi->user);
    rc = ssh_gssapi_match(session, &selected);
    if (rc == SSH_ERROR) {
        return SSH_AUTH_DENIED;
    }

    n_oids = selected->count;
    SSH_LOG(SSH_LOG_PROTOCOL, "Sending %d oids", n_oids);

    oids = calloc(n_oids, sizeof(ssh_string));
    if (oids == NULL) {
        ssh_set_error_oom(session);
        return SSH_AUTH_ERROR;
    }

    for (i=0; i<n_oids; ++i){
        oids[i] = ssh_string_new(selected->elements[i].length + 2);
        ((unsigned char *)oids[i]->data)[0] = SSH_OID_TAG;
        ((unsigned char *)oids[i]->data)[1] = selected->elements[i].length;
        memcpy((unsigned char *)oids[i]->data + 2, selected->elements[i].elements,
                selected->elements[i].length);
    }

    rc = ssh_gssapi_send_auth_mic(session, oids, n_oids);
    for (i = 0; i < n_oids; i++) {
        ssh_string_free(oids[i]);
    }
    free(oids);
    if (rc != SSH_ERROR) {
        return SSH_AUTH_AGAIN;
    }

    return SSH_AUTH_ERROR;
}
Example #22
0
File: keys.c Project: rofl0r/libssh
/**
 * @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;
}
Example #23
0
File: keys.c Project: rofl0r/libssh
static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) {
#elif defined HAVE_LIBCRYPTO
static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
#endif
    ssh_string p = NULL;
    ssh_string q = NULL;
    ssh_string g = NULL;
    ssh_string n = NULL;

    int rc = -1;

#ifdef HAVE_LIBGCRYPT
    const char *tmp = NULL;
    size_t size;
    gcry_sexp_t sexp;

    sexp = gcry_sexp_find_token(key, "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(key, "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(key, "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(key, "y", 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);

#elif defined HAVE_LIBCRYPTO
    p = make_bignum_string(key->p);
    q = make_bignum_string(key->q);
    g = make_bignum_string(key->g);
    n = make_bignum_string(key->pub_key);
    if (p == NULL || q == NULL || g == NULL || n == NULL) {
        goto error;
    }
#endif /* HAVE_LIBCRYPTO */
    if (buffer_add_ssh_string(buffer, p) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, q) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, g) < 0) {
        goto error;
    }
    if (buffer_add_ssh_string(buffer, n) < 0) {
        goto error;
    }

    rc = 0;
error:
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(sexp);
#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(n);
    ssh_string_free(n);

    return rc;
#if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO)
}
Example #24
0
File: keys.c Project: rofl0r/libssh
/*
 * This function signs the session id (known as H) as a string then
 * the content of sigbuf */
ssh_string ssh_do_sign(ssh_session session, ssh_buffer sigbuf,
                       ssh_private_key privatekey) {
    struct ssh_crypto_struct *crypto = session->current_crypto ? session->current_crypto :
                                           session->next_crypto;
    unsigned char hash[SHA_DIGEST_LEN + 1] = {0};
    ssh_string session_str = NULL;
    ssh_string signature = NULL;
    SIGNATURE *sign = NULL;
    SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t gcryhash;
#endif

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

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

    sha1_update(ctx, session_str, ssh_string_len(session_str) + 4);
    ssh_string_free(session_str);
    sha1_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
    sha1_final(hash + 1,ctx);
    hash[0] = 0;

#ifdef DEBUG_CRYPTO
    ssh_print_hexa("Hash being signed with dsa", hash + 1, SHA_DIGEST_LEN);
#endif

    sign = malloc(sizeof(SIGNATURE));
    if (sign == NULL) {
        return NULL;
    }
    ZERO_STRUCTP(sign);

    switch(privatekey->type) {
    case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, hash) ||
                gcry_pk_sign(&sign->dsa_sign, gcryhash, privatekey->dsa_priv)) {
            ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error");
            gcry_sexp_release(gcryhash);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        sign->dsa_sign = DSA_do_sign(hash + 1, SHA_DIGEST_LEN,
                                     privatekey->dsa_priv);
        if (sign->dsa_sign == NULL) {
            ssh_set_error(session, SSH_FATAL, "Signing: openssl error");
            signature_free(sign);
            return NULL;
        }
#ifdef DEBUG_CRYPTO
        ssh_print_bignum("r", sign->dsa_sign->r);
        ssh_print_bignum("s", sign->dsa_sign->s);
#endif
#endif /* HAVE_LIBCRYPTO */
        sign->rsa_sign = NULL;
        break;
    case SSH_KEYTYPE_RSA:
#ifdef HAVE_LIBGCRYPT
        if (gcry_sexp_build(&gcryhash, NULL, "(data(flags pkcs1)(hash sha1 %b))",
                            SHA_DIGEST_LEN, hash + 1) ||
                gcry_pk_sign(&sign->rsa_sign, gcryhash, privatekey->rsa_priv)) {
            ssh_set_error(session, SSH_FATAL, "Signing: libcrypt error");
            gcry_sexp_release(gcryhash);
            signature_free(sign);
            return NULL;
        }
#elif defined HAVE_LIBCRYPTO
        sign->rsa_sign = RSA_do_sign(hash + 1, SHA_DIGEST_LEN,
                                     privatekey->rsa_priv);
        if (sign->rsa_sign == NULL) {
            ssh_set_error(session, SSH_FATAL, "Signing: openssl error");
            signature_free(sign);
            return NULL;
        }
#endif
        sign->dsa_sign = NULL;
        break;
    default:
        signature_free(sign);
        return NULL;
    }
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_release(gcryhash);
#endif

    sign->type = privatekey->type;

    signature = signature_to_string(sign);
    signature_free(sign);

    return signature;
}
Example #25
0
File: keys.c Project: rofl0r/libssh
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;
}
Example #26
0
/*
 * This function concats in a buffer the values needed to do a signature
 * verification.
 */
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
                                                ssh_message msg,
                                                const char *service)
{
    struct ssh_crypto_struct *crypto =
        session->current_crypto ? session->current_crypto :
                                  session->next_crypto;
    ssh_buffer buffer;
    ssh_string str;
    int rc;

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

    /* Add session id */
    str  = ssh_string_new(crypto->digest_len);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    ssh_string_fill(str, crypto->session_id, crypto->digest_len);

    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the type */
    rc = buffer_add_u8(buffer, SSH2_MSG_USERAUTH_REQUEST);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the username */
    str = ssh_string_from_char(msg->auth_request.username);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the service name */
    str = ssh_string_from_char(service);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the method (publickey) */
    str = ssh_string_from_char("publickey");
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Has been signed (TRUE) */
    rc = buffer_add_u8(buffer, 1);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the public key algorithm */
    str = ssh_string_from_char(msg->auth_request.pubkey->type_c);
    if (str == NULL) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    /* Add the publickey as blob */
    rc = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }
    rc = buffer_add_ssh_string(buffer, str);
    string_free(str);
    if (rc < 0) {
        ssh_buffer_free(buffer);
        return NULL;
    }

    return buffer;
}
Example #27
0
int ssh_userauth1_password(ssh_session session, const char *username,
    const char *password) {
  ssh_string pwd = NULL;
  int rc;
  enter_function();
  rc = send_username(session, username);
  if (rc != SSH_AUTH_DENIED) {
    leave_function();
    return rc;
  }

  /* we trick a bit here. A known flaw in SSH1 protocol is that it's
   * easy to guess password sizes.
   * not that sure ...
   */

  /* XXX fix me here ! */
  /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */
  if(1 || strlen(password) >= 128) {
    /* not risky to disclose the size of such a big password .. */
    pwd = ssh_string_from_char(password);
    if (pwd == NULL) {
      leave_function();
      return SSH_AUTH_ERROR;
    }
  } else {
    /* fill the password string from random things. the strcpy
     * ensure there is at least a nul byte after the password.
     * most implementation won't see the garbage at end.
     * why garbage ? because nul bytes will be compressed by
     * gzip and disclose password len.
     */
    pwd = ssh_string_new(128);
    if (pwd == NULL) {
      leave_function();
      return SSH_AUTH_ERROR;
    }
    ssh_get_random( pwd->string, 128, 0);
    strcpy((char *) pwd->string, password);
  }

  if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);
    leave_function();
    return SSH_AUTH_ERROR;
  }
  if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);
    leave_function();
    return SSH_AUTH_ERROR;
  }

  ssh_string_burn(pwd);
  ssh_string_free(pwd);
  session->auth_state=SSH_AUTH_STATE_NONE;
  if (packet_send(session) == SSH_ERROR) {
    leave_function();
    return SSH_AUTH_ERROR;
  }
  rc = wait_auth1_status(session);
  leave_function();
  return rc;
}
Example #28
0
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string = NULL;
    ssh_string q_s_string = NULL;
    EC_KEY *ecdh_key=NULL;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

    enter_function();

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

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

    /* Build server's keypair */

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

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

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

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

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

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

    /* Send the MSG_NEWKEYS */
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
      goto error;
    }
    session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
    rc=packet_send(session);
    ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
    return rc;
  error:
    return SSH_ERROR;
}
Example #29
0
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string;
    ssh_string q_s_string;
    EC_KEY *ecdh_key;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

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

    /* Build server's keypair */

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

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

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

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

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

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

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

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

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

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

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

    ssh_string_free(sig_blob);

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

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

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

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

    return rc;
}
Example #30
0
File: pki.c Project: codinn/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, ssh_buffer_get(sigbuf), ssh_buffer_get_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,
                             ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf));
        if (rc != SSH_OK) {
            ssh_string_free(session_id);
            ssh_buffer_free(buf);
            return NULL;
        }

        sig = pki_do_sign(privkey,
                          ssh_buffer_get(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, ssh_buffer_get(sigbuf), ssh_buffer_get_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;
}