diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2011-08-07 14:00:42 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2011-08-08 15:28:31 +0200 |
commit | 9569d053d8f419ebd7fcdecd2c6e18ff86e34c86 (patch) | |
tree | 672c98de97f7f1ba2b17a69982a02266b9787da0 /src/pki_crypto.c | |
parent | 028888719a54794f998cc3572419361a73674929 (diff) | |
download | libssh-9569d053d8f419ebd7fcdecd2c6e18ff86e34c86.tar.gz libssh-9569d053d8f419ebd7fcdecd2c6e18ff86e34c86.tar.xz libssh-9569d053d8f419ebd7fcdecd2c6e18ff86e34c86.zip |
pki: Improve ssh_pki_import_privkey_base64().
Diffstat (limited to 'src/pki_crypto.c')
-rw-r--r-- | src/pki_crypto.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/pki_crypto.c b/src/pki_crypto.c index c6b9224..db29a2e 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -36,6 +36,7 @@ #include "libssh/libssh.h" #include "libssh/session.h" #include "libssh/callbacks.h" +#include "libssh/pki.h" static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { ssh_session session = userdata; @@ -66,4 +67,100 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { return 0; } +ssh_key pki_private_key_from_base64(ssh_session session, + const char *b64_key, + const char *passphrase) { + BIO *mem = NULL; + DSA *dsa = NULL; + RSA *rsa = NULL; + ssh_key key; + enum ssh_keytypes_e type; + + /* needed for openssl initialization */ + if (ssh_init() < 0) { + return NULL; + } + + type = pki_privatekey_type_from_string(b64_key); + if (type == SSH_KEYTYPE_UNKNOWN) { + ssh_set_error(session, SSH_FATAL, "Unknown or invalid private key."); + return NULL; + } + + mem = BIO_new_mem_buf((void*)b64_key, -1); + + switch (type) { + case SSH_KEYTYPE_DSS: + if (passphrase == NULL) { + if (session->common.callbacks && session->common.callbacks->auth_function) { + dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, session); + } else { + /* openssl uses its own callback to get the passphrase here */ + dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, NULL); + } + } else { + dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, (void *) passphrase); + } + + BIO_free(mem); + + if (dsa == NULL) { + ssh_set_error(session, SSH_FATAL, + "Parsing private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NULL; + } + + break; + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: + if (passphrase == NULL) { + if (session->common.callbacks && session->common.callbacks->auth_function) { + rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, session); + } else { + /* openssl uses its own callback to get the passphrase here */ + rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL); + } + } else { + rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, (void *) passphrase); + } + + BIO_free(mem); + + if (rsa == NULL) { + ssh_set_error(session, SSH_FATAL, + "Parsing private key: %s", + ERR_error_string(ERR_get_error(),NULL)); + return NULL; + } + + break; + case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_UNKNOWN: + BIO_free(mem); + ssh_set_error(session, SSH_FATAL, + "Unkown or invalid private key type %d", type); + return NULL; + } + + key = ssh_key_new(); + if (key == NULL) { + goto fail; + } + + key->type = type; + key->type_c = ssh_key_type_to_char(type); + key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; + key->dsa = dsa; + key->rsa = rsa; + + return key; +fail: + ssh_key_free(key); + DSA_free(dsa); + RSA_free(rsa); + + return NULL; +} + #endif /* _PKI_CRYPTO_H */ |