Esempio n. 1
0
File: pki.c Progetto: codinn/libssh
/**
 * @brief Compare keys if they are equal.
 *
 * @param[in] k1        The first key to compare.
 *
 * @param[in] k2        The second key to compare.
 *
 * @param[in] what      What part or type of the key do you want to compare.
 *
 * @return              0 if equal, 1 if not.
 */
int ssh_key_cmp(const ssh_key k1,
                const ssh_key k2,
                enum ssh_keycmp_e what)
{
    if (k1 == NULL || k2 == NULL) {
        return 1;
    }

    if (k1->type != k2->type) {
        SSH_LOG(SSH_LOG_WARN, "key types don't match!");
        return 1;
    }

    if (what == SSH_KEY_CMP_PRIVATE) {
        if (!ssh_key_is_private(k1) ||
            !ssh_key_is_private(k2)) {
            return 1;
        }
    }

    if (k1->type == SSH_KEYTYPE_ED25519) {
        return pki_ed25519_key_cmp(k1, k2, what);
    }

    return pki_key_compare(k1, k2, what);
}
Esempio n. 2
0
ssh_key pki_publickey_from_privatekey(ssh_key privkey) {
    ssh_key pubkey = NULL;

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

    pubkey = ssh_key_new();
    if (pubkey == NULL) {
        return NULL;
    }
    pubkey->type = privkey->type;

    switch (pubkey->type) {
        case SSH_KEYTYPE_DSS:
            pubkey->dsa = DSA_new();
            if (pubkey->dsa == NULL) {
                goto fail;
            }
            pubkey->dsa->p = BN_dup(privkey->dsa->p);
            pubkey->dsa->q = BN_dup(privkey->dsa->q);
            pubkey->dsa->g = BN_dup(privkey->dsa->g);
            pubkey->dsa->pub_key = BN_dup(privkey->dsa->pub_key);
            if (pubkey->dsa->p == NULL ||
                    pubkey->dsa->q == NULL ||
                    pubkey->dsa->g == NULL ||
                    pubkey->dsa->pub_key == NULL) {
                goto fail;
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            pubkey->rsa = RSA_new();
            if (pubkey->rsa == NULL) {
                goto fail;
            }
            pubkey->rsa->e = BN_dup(privkey->rsa->e);
            pubkey->rsa->n = BN_dup(privkey->rsa->n);
            if (pubkey->rsa->e == NULL ||
                    pubkey->rsa->n == NULL) {
                goto fail;
            }
            break;
        case SSH_KEYTYPE_ECDSA:
        case SSH_KEYTYPE_UNKNOWN:
            ssh_key_free(pubkey);
            return NULL;
    }
    pubkey->type_c = ssh_key_type_to_char(privkey->type);

    return pubkey;
fail:
    ssh_key_free(pubkey);

    return NULL;
}
Esempio n. 3
0
/**
 * @brief Compare keys if they are equal.
 *
 * @param[in] k1        The first key to compare.
 *
 * @param[in] k2        The second key to compare.
 *
 * @param[in] what      What part or type of the key do you want to compare.
 *
 * @return              0 if equal, 1 if not.
 */
int ssh_key_cmp(const ssh_key k1,
                const ssh_key k2,
                enum ssh_keycmp_e what)
{
    if (k1 == NULL || k2 == NULL) {
        return 1;
    }

    if (k1->type != k2->type) {
        ssh_pki_log("key types don't macth!");
        return 1;
    }

    if (what == SSH_KEY_CMP_PRIVATE) {
        if (!ssh_key_is_private(k1) ||
            !ssh_key_is_private(k2)) {
            return 1;
        }
    }

    return pki_key_compare(k1, k2, what);
}
Esempio n. 4
0
File: pki.c Progetto: codinn/libssh
/**
 * @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;
}
Esempio n. 5
0
File: pki.c Progetto: codinn/libssh
/**
 * @brief Create a public key from a private key.
 *
 * @param[in]  privkey  The private key to get the public key from.
 *
 * @param[out] pkey     A pointer to store the newly allocated public key. You
 *                      NEED to free the key.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_key_free()
 */
int ssh_pki_export_privkey_to_pubkey(const ssh_key privkey,
                                     ssh_key *pkey)
{
    ssh_key pubkey;

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

    pubkey = pki_key_dup(privkey, 1);
    if (pubkey == NULL) {
        return SSH_ERROR;
    }

    *pkey = pubkey;
    return SSH_OK;
}
Esempio n. 6
0
File: pki.c Progetto: 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;
}
Esempio n. 7
0
File: pki.c Progetto: codinn/libssh
ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
                                         const ssh_key privkey)
{
    struct ssh_crypto_struct *crypto;
    ssh_signature sig = NULL;
    ssh_string sig_blob;
    int rc;

    if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
        return NULL;
    }
    crypto = session->next_crypto ? session->next_crypto :
                                       session->current_crypto;

    if (crypto->secret_hash == NULL){
        ssh_set_error(session,SSH_FATAL,"Missing secret_hash");
        return NULL;
    }

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

        evp(privkey->ecdsa_nid, crypto->secret_hash, crypto->digest_len,
            ehash, &elen);

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

        sig = pki_do_sign_sessionid(privkey, ehash, elen);
        if (sig == NULL) {
            return NULL;
        }
#endif
    } else if (privkey->type == SSH_KEYTYPE_ED25519) {
        sig = ssh_signature_new();
        if (sig == NULL){
            return NULL;
        }

        sig->type = privkey->type;
        sig->type_c = privkey->type_c;

        rc = pki_ed25519_sign(privkey,
                              sig,
                              crypto->secret_hash,
                              crypto->digest_len);
        if (rc != SSH_OK){
            ssh_signature_free(sig);
            sig = NULL;
        }
    } else {
        unsigned char hash[SHA_DIGEST_LEN] = {0};
        SHACTX ctx;

        ctx = sha1_init();
        if (ctx == NULL) {
            return NULL;
        }
        sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
        sha1_final(hash, ctx);

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

        sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
        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;
}
Esempio n. 8
0
File: pki.c Progetto: 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;
}
Esempio n. 9
0
/* Check that KEY is a SSH private key. */
inline int
_private_key_p (struct key_data *key)
{
  return ssh_key_is_private (key->ssh_key);
}
Esempio n. 10
0
/*
 * 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;
  SIGNATURE *sign = NULL;
  SHACTX ctx = NULL;
#ifdef HAVE_LIBGCRYPT
  gcry_sexp_t gcryhash;
#endif

  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 = malloc(sizeof(SIGNATURE));
  if (sign == NULL) {
    return NULL;
  }

  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)) {
        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);
      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)) {
        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);
      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;
}
Esempio n. 11
0
ssh_key ssh_pki_publickey_from_privatekey(ssh_key privkey) {
    ssh_key pubkey = 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 */

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

    pubkey = malloc(sizeof(struct ssh_key_struct));
    if (pubkey == NULL) {
        return NULL;
    }
    ZERO_STRUCTP(pubkey);
    pubkey->type = privkey->type;
    switch(pubkey->type) {
        case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
            sexp = gcry_sexp_find_token(privkey->dsa, "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(privkey->dsa,"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(privkey->dsa, "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(privkey->dsa,"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(&pubkey->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(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
            pubkey->dsa = DSA_new();
            if (pubkey->dsa == NULL) {
                goto error;
            }
            pubkey->dsa->p = BN_dup(privkey->dsa->p);
            pubkey->dsa->q = BN_dup(privkey->dsa->q);
            pubkey->dsa->g = BN_dup(privkey->dsa->g);
            pubkey->dsa->pub_key = BN_dup(privkey->dsa->pub_key);
            if (pubkey->dsa->p == NULL ||
                    pubkey->dsa->q == NULL ||
                    pubkey->dsa->g == NULL ||
                    pubkey->dsa->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(privkey->rsa, "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(privkey->rsa, "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(&pubkey->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 (pubkey->rsa == NULL) {
                goto error;
            }

            ssh_string_burn(e);
            ssh_string_free(e);
            ssh_string_burn(n);
            ssh_string_free(n);
#elif defined HAVE_LIBCRYPTO
            pubkey->rsa = RSA_new();
            if (pubkey->rsa == NULL) {
                goto error;
            }
            pubkey->rsa->e = BN_dup(privkey->rsa->e);
            pubkey->rsa->n = BN_dup(privkey->rsa->n);
            if (pubkey->rsa->e == NULL ||
                    pubkey->rsa->n == NULL) {
                goto error;
            }
#endif
            break;
        default:
            ssh_key_free(pubkey);
            return NULL;
    }
    pubkey->type_c = ssh_type_to_char(privkey->type);

    return pubkey;
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
    ssh_key_free(pubkey);

    return NULL;
}