summaryrefslogtreecommitdiffstats
path: root/libssh/src/pki.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/src/pki.c')
-rw-r--r--libssh/src/pki.c1649
1 files changed, 0 insertions, 1649 deletions
diff --git a/libssh/src/pki.c b/libssh/src/pki.c
deleted file mode 100644
index af472ebb..00000000
--- a/libssh/src/pki.c
+++ /dev/null
@@ -1,1649 +0,0 @@
-/*
- * known_hosts.c
- * This file is part of the SSH Library
- *
- * Copyright (c) 2010 by Aris Adamantiadis
- * Copyright (c) 2011-2013 Andreas Schneider <asn@cryptomilk.org>
- *
- * The SSH Library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at your
- * option) any later version.
- *
- * The SSH Library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the SSH Library; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-/**
- * @defgroup libssh_pki The SSH Public Key Infrastructure
- * @ingroup libssh
- *
- * Functions for the creation, importation and manipulation of public and
- * private keys in the context of the SSH protocol
- *
- * @{
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef _WIN32
-# if _MSC_VER >= 1400
-# include <io.h>
-# undef open
-# define open _open
-# undef close
-# define close _close
-# undef read
-# define read _read
-# undef unlink
-# define unlink _unlink
-# endif /* _MSC_VER */
-#endif
-
-#include "libssh/libssh.h"
-#include "libssh/session.h"
-#include "libssh/priv.h"
-#include "libssh/pki.h"
-#include "libssh/pki_priv.h"
-#include "libssh/keys.h"
-#include "libssh/buffer.h"
-#include "libssh/misc.h"
-#include "libssh/agent.h"
-
-void _ssh_pki_log(const char *function, const char *format, ...)
-{
-#ifdef DEBUG_CRYPTO
- char buffer[1024];
- va_list va;
-
- va_start(va, format);
- vsnprintf(buffer, sizeof(buffer), format, va);
- va_end(va);
-
- ssh_log_function(SSH_LOG_DEBUG, function, buffer);
-#else
- (void) function;
- (void) format;
-#endif
- return;
-}
-
-enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) {
- if (strncmp(privkey, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
- return SSH_KEYTYPE_DSS;
- }
-
- if (strncmp(privkey, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
- return SSH_KEYTYPE_RSA;
- }
-
- if (strncmp(privkey, ECDSA_HEADER_BEGIN, strlen(ECDSA_HEADER_BEGIN)) == 0) {
- return SSH_KEYTYPE_ECDSA;
- }
-
- return SSH_KEYTYPE_UNKNOWN;
-}
-
-/**
- * @brief returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
- *
- * @param[in] key the ssh_key whose ECDSA name to get
- *
- * @returns the ECDSA key name ("ecdsa-sha2-nistp256" for example)
- *
- * @returns "unknown" if the ECDSA key name is not known
- */
-const char *ssh_pki_key_ecdsa_name(const ssh_key key)
-{
-#ifdef HAVE_OPENSSL_ECC /* FIXME Better ECC check needed */
- return pki_key_ecdsa_nid_to_name(key->ecdsa_nid);
-#else
- (void) key; /* unused */
- return NULL;
-#endif
-}
-
-/**
- * @brief creates a new empty SSH key
- * @returns an empty ssh_key handle, or NULL on error.
- */
-ssh_key ssh_key_new (void) {
- ssh_key ptr = malloc (sizeof (struct ssh_key_struct));
- if (ptr == NULL) {
- return NULL;
- }
- ZERO_STRUCTP(ptr);
- return ptr;
-}
-
-ssh_key ssh_key_dup(const ssh_key key)
-{
- if (key == NULL) {
- return NULL;
- }
-
- return pki_key_dup(key, 0);
-}
-
-/**
- * @brief clean up the key and deallocate all existing keys
- * @param[in] key ssh_key to clean
- */
-void ssh_key_clean (ssh_key key){
- if(key == NULL)
- return;
-#ifdef HAVE_LIBGCRYPT
- if(key->dsa) gcry_sexp_release(key->dsa);
- if(key->rsa) gcry_sexp_release(key->rsa);
- if(key->ecdsa) gcry_sexp_release(key->ecdsa);
-#elif defined HAVE_LIBCRYPTO
- if(key->dsa) DSA_free(key->dsa);
- if(key->rsa) RSA_free(key->rsa);
-#ifdef HAVE_OPENSSL_ECC
- if(key->ecdsa) EC_KEY_free(key->ecdsa);
-#endif /* HAVE_OPENSSL_ECC */
-#endif
- if (key->ed25519_privkey != NULL){
- BURN_BUFFER(key->ed25519_privkey, sizeof(ed25519_privkey));
- SAFE_FREE(key->ed25519_privkey);
- }
- SAFE_FREE(key->ed25519_pubkey);
- key->flags=SSH_KEY_FLAG_EMPTY;
- key->type=SSH_KEYTYPE_UNKNOWN;
- key->ecdsa_nid = 0;
- key->type_c=NULL;
- key->dsa = NULL;
- key->rsa = NULL;
- key->ecdsa = NULL;
-}
-
-/**
- * @brief deallocate a SSH key
- * @param[in] key ssh_key handle to free
- */
-void ssh_key_free (ssh_key key){
- if(key){
- ssh_key_clean(key);
- SAFE_FREE(key);
- }
-}
-
-/**
- * @brief returns the type of a ssh key
- * @param[in] key the ssh_key handle
- * @returns one of SSH_KEYTYPE_RSA,SSH_KEYTYPE_DSS,SSH_KEYTYPE_RSA1
- * @returns SSH_KEYTYPE_UNKNOWN if the type is unknown
- */
-enum ssh_keytypes_e ssh_key_type(const ssh_key key){
- if (key == NULL) {
- return SSH_KEYTYPE_UNKNOWN;
- }
- return key->type;
-}
-
-/**
- * @brief Convert a key type to a string.
- *
- * @param[in] type The type to convert.
- *
- * @return A string for the keytype or NULL if unknown.
- */
-const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
- switch (type) {
- case SSH_KEYTYPE_DSS:
- return "ssh-dss";
- case SSH_KEYTYPE_RSA:
- return "ssh-rsa";
- case SSH_KEYTYPE_RSA1:
- return "ssh-rsa1";
- case SSH_KEYTYPE_ECDSA:
- return "ssh-ecdsa";
- case SSH_KEYTYPE_ED25519:
- return "ssh-ed25519";
- case SSH_KEYTYPE_UNKNOWN:
- return NULL;
- }
-
- /* We should never reach this */
- return NULL;
-}
-
-/**
- * @brief Convert a ssh key name to a ssh key type.
- *
- * @param[in] name The name to convert.
- *
- * @return The enum ssh key type.
- */
-enum ssh_keytypes_e ssh_key_type_from_name(const char *name) {
- if (name == NULL) {
- return SSH_KEYTYPE_UNKNOWN;
- }
-
- if (strcmp(name, "rsa1") == 0) {
- return SSH_KEYTYPE_RSA1;
- } else if (strcmp(name, "rsa") == 0) {
- return SSH_KEYTYPE_RSA;
- } else if (strcmp(name, "dsa") == 0) {
- return SSH_KEYTYPE_DSS;
- } else if (strcmp(name, "ssh-rsa1") == 0) {
- return SSH_KEYTYPE_RSA1;
- } else if (strcmp(name, "ssh-rsa") == 0) {
- return SSH_KEYTYPE_RSA;
- } else if (strcmp(name, "ssh-dss") == 0) {
- return SSH_KEYTYPE_DSS;
- } else if (strcmp(name, "ssh-ecdsa") == 0
- || strcmp(name, "ecdsa") == 0
- || strcmp(name, "ecdsa-sha2-nistp256") == 0
- || strcmp(name, "ecdsa-sha2-nistp384") == 0
- || strcmp(name, "ecdsa-sha2-nistp521") == 0) {
- return SSH_KEYTYPE_ECDSA;
- } else if (strcmp(name, "ssh-ed25519") == 0){
- return SSH_KEYTYPE_ED25519;
- }
-
- return SSH_KEYTYPE_UNKNOWN;
-}
-
-/**
- * @brief Check if the key has/is a public key.
- *
- * @param[in] k The key to check.
- *
- * @return 1 if it is a public key, 0 if not.
- */
-int ssh_key_is_public(const ssh_key k) {
- if (k == NULL) {
- return 0;
- }
-
- return (k->flags & SSH_KEY_FLAG_PUBLIC);
-}
-
-/**
- * @brief Check if the key is a private key.
- *
- * @param[in] k The key to check.
- *
- * @return 1 if it is a private key, 0 if not.
- */
-int ssh_key_is_private(const ssh_key k) {
- if (k == NULL) {
- return 0;
- }
-
- return (k->flags & SSH_KEY_FLAG_PRIVATE);
-}
-
-/**
- * @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 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);
-}
-
-ssh_signature ssh_signature_new(void)
-{
- struct ssh_signature_struct *sig;
-
- sig = malloc(sizeof(struct ssh_signature_struct));
- if (sig == NULL) {
- return NULL;
- }
- ZERO_STRUCTP(sig);
-
- return sig;
-}
-
-void ssh_signature_free(ssh_signature sig)
-{
- if (sig == NULL) {
- return;
- }
-
- switch(sig->type) {
- case SSH_KEYTYPE_DSS:
-#ifdef HAVE_LIBGCRYPT
- gcry_sexp_release(sig->dsa_sig);
-#elif defined HAVE_LIBCRYPTO
- DSA_SIG_free(sig->dsa_sig);
-#endif
- break;
- case SSH_KEYTYPE_RSA:
- case SSH_KEYTYPE_RSA1:
-#ifdef HAVE_LIBGCRYPT
- gcry_sexp_release(sig->rsa_sig);
-#elif defined HAVE_LIBCRYPTO
- SAFE_FREE(sig->rsa_sig);
-#endif
- break;
- case SSH_KEYTYPE_ECDSA:
-#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ECC)
- ECDSA_SIG_free(sig->ecdsa_sig);
-#endif
- break;
- case SSH_KEYTYPE_ED25519:
- SAFE_FREE(sig->ed25519_sig);
- break;
- case SSH_KEYTYPE_UNKNOWN:
- break;
- }
-
- SAFE_FREE(sig);
-}
-
-/**
- * @brief import a base64 formated key from a memory c-string
- *
- * @param[in] b64_key The c-string holding the base64 encoded key
- *
- * @param[in] passphrase The passphrase to decrypt the key, or NULL
- *
- * @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[out] pkey A pointer where the allocated key can be stored. You
- * need to free the memory.
- *
- * @return SSH_ERROR in case of error, SSH_OK otherwise.
- *
- * @see ssh_key_free()
- */
-int ssh_pki_import_privkey_base64(const char *b64_key,
- const char *passphrase,
- ssh_auth_callback auth_fn,
- void *auth_data,
- ssh_key *pkey)
-{
- ssh_key key;
-
- if (b64_key == NULL || pkey == NULL) {
- return SSH_ERROR;
- }
-
- if (b64_key == NULL || !*b64_key) {
- return SSH_ERROR;
- }
-
- ssh_pki_log("Trying to decode privkey passphrase=%s",
- passphrase ? "true" : "false");
-
- key = pki_private_key_from_base64(b64_key, passphrase, auth_fn, auth_data);
- if (key == NULL) {
- return SSH_ERROR;
- }
-
- *pkey = key;
-
- return SSH_OK;
-}
-
-/**
- * @brief Import a key from a file.
- *
- * @param[in] filename The filename of the the private key.
- *
- * @param[in] passphrase The passphrase to decrypt the private key. Set to NULL
- * if none is needed or it is unknown.
- *
- * @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[out] pkey A pointer to store the allocated ssh_key. You need to
- * free the key.
- *
- * @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
- * denied, SSH_ERROR otherwise.
- *
- * @see ssh_key_free()
- **/
-int ssh_pki_import_privkey_file(const char *filename,
- const char *passphrase,
- ssh_auth_callback auth_fn,
- void *auth_data,
- ssh_key *pkey) {
- struct stat sb;
- char *key_buf;
- ssh_key key;
- FILE *file;
- off_t size;
- int rc;
-
- if (pkey == NULL || filename == NULL || *filename == '\0') {
- return SSH_ERROR;
- }
-
- file = fopen(filename, "rb");
- if (file == NULL) {
- ssh_pki_log("Error opening %s: %s",
- filename, strerror(errno));
- return SSH_EOF;
- }
-
- rc = fstat(fileno(file), &sb);
- if (rc < 0) {
- fclose(file);
- ssh_pki_log("Error getting stat of %s: %s",
- filename, strerror(errno));
- switch (errno) {
- case ENOENT:
- case EACCES:
- return SSH_EOF;
- }
-
- return SSH_ERROR;
- }
-
- if (sb.st_size > MAX_PRIVKEY_SIZE) {
- ssh_pki_log("Private key is bigger than 4M.");
- fclose(file);
- return SSH_ERROR;
- }
-
- key_buf = malloc(sb.st_size + 1);
- if (key_buf == NULL) {
- fclose(file);
- ssh_pki_log("Out of memory!");
- return SSH_ERROR;
- }
-
- size = fread(key_buf, 1, sb.st_size, file);
- fclose(file);
-
- if (size != sb.st_size) {
- SAFE_FREE(key_buf);
- ssh_pki_log("Error reading %s: %s",
- filename, strerror(errno));
- return SSH_ERROR;
- }
- key_buf[size] = 0;
-
- key = pki_private_key_from_base64(key_buf, passphrase, auth_fn, auth_data);
- SAFE_FREE(key_buf);
- if (key == NULL) {
- return SSH_ERROR;
- }
-
- *pkey = key;
- return SSH_OK;
-}
-
-/**
- * @brief Export a private key to a pam file on disk.
- *
- * @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;
- }
-
-
- 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;
-}
-
-/* temporary function to migrate seemlessly to ssh_key */
-ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) {
- ssh_public_key pub;
- ssh_key tmp;
-
- if(key == NULL) {
- return NULL;
- }
-
- tmp = ssh_key_dup(key);
- if (tmp == NULL) {
- return NULL;
- }
-
- pub = malloc(sizeof(struct ssh_public_key_struct));
- if (pub == NULL) {
- ssh_key_free(tmp);
- return NULL;
- }
- ZERO_STRUCTP(pub);
-
- pub->type = tmp->type;
- pub->type_c = tmp->type_c;
-
- pub->dsa_pub = tmp->dsa;
- tmp->dsa = NULL;
- pub->rsa_pub = tmp->rsa;
- tmp->rsa = NULL;
-
- ssh_key_free(tmp);
-
- return pub;
-}
-
-ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
- ssh_private_key privkey;
-
- privkey = malloc(sizeof(struct ssh_private_key_struct));
- if (privkey == NULL) {
- ssh_key_free(key);
- return NULL;
- }
-
- privkey->type = key->type;
- privkey->dsa_priv = key->dsa;
- privkey->rsa_priv = key->rsa;
-
- return privkey;
-}
-
-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 = buffer_get_ssh_string(buffer);
- if (p == NULL) {
- goto fail;
- }
- q = buffer_get_ssh_string(buffer);
- if (q == NULL) {
- ssh_string_burn(p);
- ssh_string_free(p);
-
- goto fail;
- }
- g = 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 = 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 = buffer_get_ssh_string(buffer);
- if (e == NULL) {
- goto fail;
- }
- n = 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 = 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 = 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 = buffer_get_ssh_string(buffer);
- if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
- ssh_pki_log("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_UNKNOWN:
- default:
- ssh_pki_log("Unknown public key protocol %d", type);
- goto fail;
- }
-
- *pkey = key;
- return SSH_OK;
-fail:
- ssh_key_free(key);
-
- return SSH_ERROR;
-}
-
-/**
- * @brief Import a base64 formated public key from a memory c-string.
- *
- * @param[in] b64_key The base64 key to format.
- *
- * @param[in] type The type of the key to format.
- *
- * @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_base64(const char *b64_key,
- enum ssh_keytypes_e type,
- ssh_key *pkey) {
- ssh_buffer buffer;
- ssh_string type_s;
- int rc;
-
- if (b64_key == NULL || pkey == NULL) {
- return SSH_ERROR;
- }
-
- buffer = base64_to_bin(b64_key);
- if (buffer == NULL) {
- return SSH_ERROR;
- }
-
- type_s = buffer_get_ssh_string(buffer);
- if (type_s == NULL) {
- ssh_buffer_free(buffer);
- return SSH_ERROR;
- }
- ssh_string_free(type_s);
-
- rc = pki_import_pubkey_buffer(buffer, type, pkey);
- ssh_buffer_free(buffer);
-
- return rc;
-}
-
-/**
- * @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_pki_log("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_pki_log("Out of memory!");
- goto fail;
- }
-
- type_s = buffer_get_ssh_string(buffer);
- if (type_s == NULL) {
- ssh_pki_log("Out of memory!");
- goto fail;
- }
-
- type = ssh_key_type_from_name(ssh_string_get_char(type_s));
- if (type == SSH_KEYTYPE_UNKNOWN) {
- ssh_pki_log("Unknown key type found!");
- goto fail;
- }
- ssh_string_free(type_s);
-
- 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;
-}
-
-/**
- * @brief Import a public key from the given filename.
- *
- * @param[in] filename The path to the public key.
- *
- * @param[out] pkey A pointer to store the allocated public key. You need to
- * free the memory.
- *
- * @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission
- * denied, SSH_ERROR otherwise.
- *
- * @see ssh_key_free()
- */
-int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
-{
- enum ssh_keytypes_e type;
- struct stat sb;
- char *key_buf, *p;
- const char *q;
- FILE *file;
- off_t size;
- int rc;
-
- if (pkey == NULL || filename == NULL || *filename == '\0') {
- return SSH_ERROR;
- }
-
- file = fopen(filename, "r");
- if (file == NULL) {
- ssh_pki_log("Error opening %s: %s",
- filename, strerror(errno));
- return SSH_EOF;
- }
-
- rc = fstat(fileno(file), &sb);
- if (rc < 0) {
- fclose(file);
- ssh_pki_log("Error gettint stat of %s: %s",
- filename, strerror(errno));
- switch (errno) {
- case ENOENT:
- case EACCES:
- return SSH_EOF;
- }
- return SSH_ERROR;
- }
-
- if (sb.st_size > MAX_PUBKEY_SIZE) {
- fclose(file);
- return SSH_ERROR;
- }
-
- key_buf = malloc(sb.st_size + 1);
- if (key_buf == NULL) {
- fclose(file);
- ssh_pki_log("Out of memory!");
- return SSH_ERROR;
- }
-
- size = fread(key_buf, 1, sb.st_size, file);
- fclose(file);
-
- if (size != sb.st_size) {
- SAFE_FREE(key_buf);
- ssh_pki_log("Error reading %s: %s",
- filename, strerror(errno));
- return SSH_ERROR;
- }
- key_buf[size] = '\0';
-
- q = p = key_buf;
- while (!isspace((int)*p)) p++;
- *p = '\0';
-
- type = ssh_key_type_from_name(q);
- if (type == SSH_KEYTYPE_UNKNOWN) {
- SAFE_FREE(key_buf);
- return SSH_ERROR;
- }
- q = ++p;
- while (!isspace((int)*p)) p++;
- *p = '\0';
-
- rc = ssh_pki_import_pubkey_base64(q, type, pkey);
- SAFE_FREE(key_buf);
-
- return rc;
-}
-
-/**
- * @brief Generates a keypair.
- *
- * @param[in] type Type of key to create
- *
- * @param[in] parameter Parameter to the creation of key:
- * rsa : length of the key in bits (e.g. 1024, 2048, 4096)
- * dsa : length of the key in bits (e.g. 1024, 2048, 3072)
- * ecdsa : bits of the key (e.g. 256, 384, 512)
- * @param[out] pkey A pointer to store the allocated private key. You need
- * to free the memory.
- *
- * @return SSH_OK on success, SSH_ERROR on error.
- *
- * @warning Generating a key pair may take some time.
- */
-int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
- ssh_key *pkey){
- int rc;
- ssh_key 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_PRIVATE | SSH_KEY_FLAG_PUBLIC;
-
- switch(type){
- case SSH_KEYTYPE_RSA:
- case SSH_KEYTYPE_RSA1:
- rc = pki_key_generate_rsa(key, parameter);
- if(rc == SSH_ERROR)
- goto error;
- break;
- case SSH_KEYTYPE_DSS:
- rc = pki_key_generate_dss(key, parameter);
- if(rc == SSH_ERROR)
- goto error;
- break;
- case SSH_KEYTYPE_ECDSA:
-#ifdef HAVE_ECC
- rc = pki_key_generate_ecdsa(key, parameter);
- if (rc == SSH_ERROR) {
- goto error;
- }
-
- /* Update key type */
- key->type_c = ssh_pki_key_ecdsa_name(key);
- break;
-#endif
- case SSH_KEYTYPE_ED25519:
- rc = pki_key_generate_ed25519(key);
- if (rc == SSH_ERROR) {
- goto error;
- }
- break;
- case SSH_KEYTYPE_UNKNOWN:
- goto error;
- }
-
- *pkey = key;
- return SSH_OK;
-error:
- ssh_key_free(key);
- return SSH_ERROR;
-}
-
-/**
- * @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 A public key, NULL 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;
-}
-
-/**
- * @internal
- *
- * @brief Create a key_blob from a public key.
- *
- * The "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
- * Algorithms" for any of the supported protocol 2 key types.
- *
- * @param[in] key A public or private key to create the public ssh_string
- * from.
- *
- * @param[out] pblob A pointer to store the newly allocated key blob. You
- * NEED to free it.
- *
- * @return SSH_OK on success, SSH_ERROR otherwise.
- *
- * @see ssh_string_free()
- */
-int ssh_pki_export_pubkey_blob(const ssh_key key,
- ssh_string *pblob)
-{
- ssh_string blob;
-
- if (key == NULL) {
- return SSH_OK;
- }
-
- blob = pki_publickey_to_blob(key);
- if (blob == NULL) {
- return SSH_ERROR;
- }
-
- *pblob = blob;
- return SSH_OK;
-}
-
-/**
- * @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;
-}
-
-int ssh_pki_export_pubkey_file(const ssh_key key,
- const char *filename)
-{
- char key_buf[4096];
- char host[256];
- char *b64_key;
- char *user;
- FILE *fp;
- int rc;
-
- if (key == NULL || filename == NULL || *filename == '\0') {
- return SSH_ERROR;
- }
-
- user = ssh_get_local_username();
- if (user == NULL) {
- return SSH_ERROR;
- }
-
- rc = gethostname(host, sizeof(host));
- if (rc < 0) {
- free(user);
- return SSH_ERROR;
- }
-
- rc = ssh_pki_export_pubkey_base64(key, &b64_key);
- if (rc < 0) {
- free(user);
- return SSH_ERROR;
- }
-
- rc = snprintf(key_buf, sizeof(key_buf),
- "%s %s %s@%s\n",
- key->type_c,
- b64_key,
- user,
- host);
- free(user);
- free(b64_key);
- if (rc < 0) {
- return SSH_ERROR;
- }
-
- fp = fopen(filename, "w+");
- if (fp == NULL) {
- return SSH_ERROR;
- }
- rc = fwrite(key_buf, strlen(key_buf), 1, fp);
- if (rc != 1 || ferror(fp)) {
- fclose(fp);
- unlink(filename);
- return SSH_ERROR;
- }
- fclose(fp);
-
- return SSH_OK;
-}
-
-int ssh_pki_export_pubkey_rsa1(const ssh_key key,
- const char *host,
-