diff options
Diffstat (limited to 'libssh/src/pki_crypto.c')
-rw-r--r-- | libssh/src/pki_crypto.c | 1671 |
1 files changed, 0 insertions, 1671 deletions
diff --git a/libssh/src/pki_crypto.c b/libssh/src/pki_crypto.c deleted file mode 100644 index 5706fdf0..00000000 --- a/libssh/src/pki_crypto.c +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * pki_crypto.c - PKI infrastructure using OpenSSL - * - * This file is part of the SSH Library - * - * Copyright (c) 2003-2009 by Aris Adamantiadis - * Copyright (c) 2009-2013 by 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. - */ - -#ifndef _PKI_CRYPTO_H -#define _PKI_CRYPTO_H - -#include "libssh/priv.h" - -#include <openssl/pem.h> -#include <openssl/dsa.h> -#include <openssl/err.h> -#include <openssl/rsa.h> - -#ifdef HAVE_OPENSSL_EC_H -#include <openssl/ec.h> -#endif -#ifdef HAVE_OPENSSL_ECDSA_H -#include <openssl/ecdsa.h> -#endif - -#include "libssh/libssh.h" -#include "libssh/buffer.h" -#include "libssh/session.h" -#include "libssh/pki.h" -#include "libssh/pki_priv.h" -#include "libssh/bignum.h" - -struct pem_get_password_struct { - ssh_auth_callback fn; - void *data; -}; - -static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { - struct pem_get_password_struct *pgp = userdata; - - (void) rwflag; /* unused */ - - if (buf == NULL) { - return 0; - } - - memset(buf, '\0', size); - if (pgp) { - int rc; - - rc = pgp->fn("Passphrase for private key:", - buf, size, 0, 0, - pgp->data); - if (rc == 0) { - return strlen(buf); - } - } - - return 0; -} - -#ifdef HAVE_OPENSSL_ECC -static int pki_key_ecdsa_to_nid(EC_KEY *k) -{ - const EC_GROUP *g = EC_KEY_get0_group(k); - int nid; - - nid = EC_GROUP_get_curve_name(g); - if (nid) { - return nid; - } - - return -1; -} - -const char *pki_key_ecdsa_nid_to_name(int nid) -{ - switch (nid) { - case NID_X9_62_prime256v1: - return "ecdsa-sha2-nistp256"; - case NID_secp384r1: - return "ecdsa-sha2-nistp384"; - case NID_secp521r1: - return "ecdsa-sha2-nistp521"; - default: - break; - } - - return "unknown"; -} - -static const char *pki_key_ecdsa_nid_to_char(int nid) -{ - switch (nid) { - case NID_X9_62_prime256v1: - return "nistp256"; - case NID_secp384r1: - return "nistp384"; - case NID_secp521r1: - return "nistp521"; - default: - break; - } - - return "unknown"; -} - -int pki_key_ecdsa_nid_from_name(const char *name) -{ - if (strcmp(name, "nistp256") == 0) { - return NID_X9_62_prime256v1; - } else if (strcmp(name, "nistp384") == 0) { - return NID_secp384r1; - } else if (strcmp(name, "nistp521") == 0) { - return NID_secp521r1; - } - - return -1; -} - -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; -} - -int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) -{ - EC_POINT *p; - const EC_GROUP *g; - int ok; - - key->ecdsa_nid = nid; - key->type_c = pki_key_ecdsa_nid_to_name(nid); - - key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (key->ecdsa == NULL) { - return -1; - } - - g = EC_KEY_get0_group(key->ecdsa); - - p = EC_POINT_new(g); - if (p == NULL) { - return -1; - } - - ok = EC_POINT_oct2point(g, - p, - ssh_string_data(e), - ssh_string_len(e), - NULL); - if (!ok) { - EC_POINT_free(p); - return -1; - } - - /* EC_KEY_set_public_key duplicates p */ - ok = EC_KEY_set_public_key(key->ecdsa, p); - EC_POINT_free(p); - if (!ok) { - return -1; - } - - return 0; -} -#endif - -ssh_key pki_key_dup(const ssh_key key, int demote) -{ - ssh_key new; - int rc; - - new = ssh_key_new(); - if (new == NULL) { - return NULL; - } - - new->type = key->type; - new->type_c = key->type_c; - if (demote) { - new->flags = SSH_KEY_FLAG_PUBLIC; - } else { - new->flags = key->flags; - } - - switch (key->type) { - case SSH_KEYTYPE_DSS: - new->dsa = DSA_new(); - if (new->dsa == NULL) { - goto fail; - } - - /* - * p = public prime number - * q = public 160-bit subprime, q | p-1 - * g = public generator of subgroup - * pub_key = public key y = g^x - * priv_key = private key x - */ - new->dsa->p = BN_dup(key->dsa->p); - if (new->dsa->p == NULL) { - goto fail; - } - - new->dsa->q = BN_dup(key->dsa->q); - if (new->dsa->q == NULL) { - goto fail; - } - - new->dsa->g = BN_dup(key->dsa->g); - if (new->dsa->g == NULL) { - goto fail; - } - - new->dsa->pub_key = BN_dup(key->dsa->pub_key); - if (new->dsa->pub_key == NULL) { - goto fail; - } - - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - new->dsa->priv_key = BN_dup(key->dsa->priv_key); - if (new->dsa->priv_key == NULL) { - goto fail; - } - } - - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - new->rsa = RSA_new(); - if (new->rsa == NULL) { - goto fail; - } - - /* - * n = public modulus - * e = public exponent - * d = private exponent - * p = secret prime factor - * q = secret prime factor - * dmp1 = d mod (p-1) - * dmq1 = d mod (q-1) - * iqmp = q^-1 mod p - */ - new->rsa->n = BN_dup(key->rsa->n); - if (new->rsa->n == NULL) { - goto fail; - } - - new->rsa->e = BN_dup(key->rsa->e); - if (new->rsa->e == NULL) { - goto fail; - } - - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - new->rsa->d = BN_dup(key->rsa->d); - if (new->rsa->d == NULL) { - goto fail; - } - - /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the - * RSA operations are much faster when these values are available. - */ - if (key->rsa->p != NULL) { - new->rsa->p = BN_dup(key->rsa->p); - if (new->rsa->p == NULL) { - goto fail; - } - } - - if (key->rsa->q != NULL) { - new->rsa->q = BN_dup(key->rsa->q); - if (new->rsa->q == NULL) { - goto fail; - } - } - - if (key->rsa->dmp1 != NULL) { - new->rsa->dmp1 = BN_dup(key->rsa->dmp1); - if (new->rsa->dmp1 == NULL) { - goto fail; - } - } - - if (key->rsa->dmq1 != NULL) { - new->rsa->dmq1 = BN_dup(key->rsa->dmq1); - if (new->rsa->dmq1 == NULL) { - goto fail; - } - } - - if (key->rsa->iqmp != NULL) { - new->rsa->iqmp = BN_dup(key->rsa->iqmp); - if (new->rsa->iqmp == NULL) { - goto fail; - } - } - } - - break; - case SSH_KEYTYPE_ECDSA: -#ifdef HAVE_OPENSSL_ECC - new->ecdsa_nid = key->ecdsa_nid; - - /* privkey -> pubkey */ - if (demote && ssh_key_is_private(key)) { - const EC_POINT *p; - int ok; - - new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (new->ecdsa == NULL) { - goto fail; - } - - p = EC_KEY_get0_public_key(key->ecdsa); - if (p == NULL) { - goto fail; - } - - ok = EC_KEY_set_public_key(new->ecdsa, p); - if (!ok) { - goto fail; - } - } else { - new->ecdsa = EC_KEY_dup(key->ecdsa); - } - break; -#endif - case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_key_dup(new, key); - if (rc != SSH_OK) { - goto fail; - } - break; - case SSH_KEYTYPE_UNKNOWN: - default: - ssh_key_free(new); - return NULL; - } - - return new; -fail: - ssh_key_free(new); - return NULL; -} - -int pki_key_generate_rsa(ssh_key key, int parameter){ - BIGNUM *e; - int rc; - - e = BN_new(); - key->rsa = RSA_new(); - - BN_set_word(e, 65537); - rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL); - - BN_free(e); - - if (rc == -1 || key->rsa == NULL) - return SSH_ERROR; - return SSH_OK; -} - -int pki_key_generate_dss(ssh_key key, int parameter){ - int rc; - key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL, - NULL, NULL); - if(key->dsa == NULL){ - return SSH_ERROR; - } - rc = DSA_generate_key(key->dsa); - if (rc != 1){ - DSA_free(key->dsa); - key->dsa=NULL; - return SSH_ERROR; - } - return SSH_OK; -} - -#ifdef HAVE_OPENSSL_ECC -int pki_key_generate_ecdsa(ssh_key key, int parameter) { - int nid; - int ok; - - switch (parameter) { - case 384: - nid = NID_secp384r1; - break; - case 512: - nid = NID_secp521r1; - break; - case 256: - default: - nid = NID_X9_62_prime256v1; - } - - key->ecdsa_nid = nid; - key->type = SSH_KEYTYPE_ECDSA; - key->type_c = pki_key_ecdsa_nid_to_name(nid); - - key->ecdsa = EC_KEY_new_by_curve_name(nid); - if (key->ecdsa == NULL) { - return SSH_ERROR; - } - - ok = EC_KEY_generate_key(key->ecdsa); - if (!ok) { - EC_KEY_free(key->ecdsa); - return SSH_ERROR; - } - - EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE); - - return SSH_OK; -} -#endif - -int pki_key_compare(const ssh_key k1, - const ssh_key k2, - enum ssh_keycmp_e what) -{ - switch (k1->type) { - case SSH_KEYTYPE_DSS: - if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { - return 1; - } - if (bignum_cmp(k1->dsa->p, k2->dsa->p) != 0) { - return 1; - } - if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) { - return 1; - } - if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) { - return 1; - } - if (bignum_cmp(k1->dsa->pub_key, k2->dsa->pub_key) != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(k1->dsa->priv_key, k2->dsa->priv_key) != 0) { - return 1; - } - } - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { - return 1; - } - if (bignum_cmp(k1->rsa->e, k2->rsa->e) != 0) { - return 1; - } - if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(k1->rsa->p, k2->rsa->p) != 0) { - return 1; - } - - if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) { - return 1; - } - } - break; - case SSH_KEYTYPE_ECDSA: -#ifdef HAVE_OPENSSL_ECC - { - const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa); - const EC_POINT *p2 = EC_KEY_get0_public_key(k2->ecdsa); - const EC_GROUP *g1 = EC_KEY_get0_group(k1->ecdsa); - const EC_GROUP *g2 = EC_KEY_get0_group(k2->ecdsa); - - if (p1 == NULL || p2 == NULL) { - return 1; - } - - if (EC_GROUP_cmp(g1, g2, NULL) != 0) { - return 1; - } - - if (EC_POINT_cmp(g1, p1, p2, NULL) != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(EC_KEY_get0_private_key(k1->ecdsa), - EC_KEY_get0_private_key(k2->ecdsa))) { - return 1; - } - } - - break; - } -#endif - case SSH_KEYTYPE_ED25519: - /* ed25519 keys handled globaly */ - case SSH_KEYTYPE_UNKNOWN: - default: - return 1; - } - - return 0; -} - -ssh_string pki_private_key_to_pem(const ssh_key key, - const char *passphrase, - ssh_auth_callback auth_fn, - void *auth_data) -{ - ssh_string blob; - BUF_MEM *buf; - BIO *mem; - int rc; - - /* needed for openssl initialization */ - if (ssh_init() < 0) { - return NULL; - } - - mem = BIO_new(BIO_s_mem()); - if (mem == NULL) { - return NULL; - } - - switch (key->type) { - case SSH_KEYTYPE_DSS: - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_DSAPrivateKey(mem, - key->dsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_DSAPrivateKey(mem, - key->dsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_RSAPrivateKey(mem, - key->rsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_RSAPrivateKey(mem, - key->rsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } - break; - case SSH_KEYTYPE_ECDSA: -#ifdef HAVE_ECC - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_ECPrivateKey(mem, - key->ecdsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_ECPrivateKey(mem, - key->ecdsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } - break; -#endif - case SSH_KEYTYPE_ED25519: - case SSH_KEYTYPE_UNKNOWN: - BIO_free(mem); - ssh_pki_log("Unkown or invalid private key type %d", key->type); - return NULL; - } - - BIO_get_mem_ptr(mem, &buf); - - blob = ssh_string_new(buf->length); - if (blob == NULL) { - goto err; - } - - ssh_string_fill(blob, buf->data, buf->length); - BIO_free(mem); - - return blob; -err: - BIO_free(mem); - return NULL; -} - -ssh_key pki_private_key_from_base64(const char *b64_key, - const char *passphrase, - ssh_auth_callback auth_fn, - void *auth_data) { - BIO *mem = NULL; - DSA *dsa = NULL; - RSA *rsa = NULL; - ssh_key key; - enum ssh_keytypes_e type; -#ifdef HAVE_OPENSSL_ECC - EC_KEY *ecdsa = NULL; -#else - void *ecdsa = NULL; -#endif - - /* needed for openssl initialization */ - if (ssh_init() < 0) { - return NULL; - } - - type = pki_privatekey_type_from_string(b64_key); - if (type == SSH_KEYTYPE_UNKNOWN) { - ssh_pki_log("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 (auth_fn) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, &pgp); - } 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_pki_log("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 (auth_fn) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, &pgp); - } 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_pki_log("Parsing private key: %s", - ERR_error_string(ERR_get_error(),NULL)); - return NULL; - } - - break; - case SSH_KEYTYPE_ECDSA: -#ifdef HAVE_OPENSSL_ECC - if (passphrase == NULL) { - if (auth_fn) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, pem_get_password, &pgp); - } else { - /* openssl uses its own callback to get the passphrase here */ - ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, NULL, NULL); - } - } else { - ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, NULL, (void *) passphrase); - } - - BIO_free(mem); - - if (ecdsa == NULL) { - ssh_pki_log("Parsing private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - break; -#endif - case SSH_KEYTYPE_ED25519: - case SSH_KEYTYPE_UNKNOWN: - BIO_free(mem); - ssh_pki_log("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; - key->ecdsa = ecdsa; -#ifdef HAVE_OPENSSL_ECC - if (key->type == SSH_KEYTYPE_ECDSA) { - key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); - key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid); - } -#endif - - return key; -fail: - ssh_key_free(key); - DSA_free(dsa); - RSA_free(rsa); -#ifdef HAVE_OPENSSL_ECC - EC_KEY_free(ecdsa); -#endif - - return NULL; -} - -int pki_pubkey_build_dss(ssh_key key, - ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey) { - key->dsa = DSA_new(); - if (key->dsa == NULL) { - return SSH_ERROR; - } - - key->dsa->p = make_string_bn(p); - key->dsa->q = make_string_bn(q); - key->dsa->g = make_string_bn(g); - key->dsa->pub_key = make_string_bn(pubkey); - if (key->dsa->p == NULL || - key->dsa->q == NULL || - key->dsa->g == NULL || - key->dsa->pub_key == NULL) { - DSA_free(key->dsa); - return SSH_ERROR; - } - - return SSH_OK; -} - -int pki_pubkey_build_rsa(ssh_key key, - ssh_string e, - ssh_string n) { - key->rsa = RSA_new(); - if (key->rsa == NULL) { - return SSH_ERROR; - } - - key->rsa->e = make_string_bn(e); - key->rsa->n = make_string_bn(n); - if (key->rsa->e == NULL || - key->rsa->n == NULL) { - RSA_free(key->rsa); - return SSH_ERROR; - } - - return SSH_OK; -} - -ssh_string pki_publickey_to_blob(const ssh_key key) -{ - ssh_buffer buffer; - ssh_string type_s; - ssh_string str = NULL; - ssh_string e = NULL; - ssh_string n = NULL; - ssh_string p = NULL; - ssh_string g = NULL; - ssh_string q = NULL; - int rc; - - buffer = ssh_buffer_new(); - if (buffer == NULL) { - return NULL; - } - - type_s = ssh_string_from_char(key->type_c); - if (type_s == NULL) { - ssh_buffer_free(buffer); - return NULL; - } - - rc = buffer_add_ssh_string(buffer, type_s); - ssh_string_free(type_s); - if (rc < 0) { - ssh_buffer_free(buffer); - return NULL; - } - - switch (key->type) { - case SSH_KEYTYPE_DSS: - p = make_bignum_string(key->dsa->p); - if (p == NULL) { - goto fail; - } - - q = make_bignum_string(key->dsa->q); - if (q == NULL) { - goto fail; - } - - g = make_bignum_string(key->dsa->g); - if (g == NULL) { - goto fail; - } - - n = make_bignum_string(key->dsa->pub_key); - if (n == NULL) { - goto fail; - } - - if (buffer_add_ssh_string(buffer, p) < 0) { - goto fail; - } - if (buffer_add_ssh_string(buffer, q) < 0) { - goto fail; - } - if (buffer_add_ssh_string(buffer, g) < 0) { - goto fail; - } - if (buffer_add_ssh_string(buffer, n) < 0) { - goto fail; - } - - ssh_string_burn(p); - ssh_string_free(p); - p = NULL; - ssh_string_burn(g); - ssh_string_free(g); - g = NULL; - ssh_string_burn(q); - ssh_string_free(q); - q = NULL; - ssh_string_burn(n); - ssh_string_free(n); - n = NULL; - - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - e = make_bignum_string(key->rsa->e); - if (e == NULL) { - goto fail; - } - - n = make_bignum_string(key->rsa->n); - if (n == NULL) { - goto fail; - } - - if (buffer_add_ssh_string(buffer, e) < 0) { - goto fail; - } - if (buffer_add_ssh_string(buffer, n) < 0) { - goto fail; - } - - ssh_string_burn(e); - ssh_string_free(e); - e = NULL; - ssh_string_burn(n); - ssh_string_free(n); - n = NULL; - - break; - case SSH_KEYTYPE_ECDSA: -#ifdef HAVE_OPENSSL_ECC - rc = ssh_buffer_reinit(buffer); - if (rc < 0) { - ssh_buffer_free(buffer); - return NULL; - } - - type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_name(key->ecdsa_nid)); - if (type_s == NULL) { - ssh_buffer_free(buffer); - return NULL; - } - - rc = buffer_add_ssh_string(buffer, type_s); - ssh_string_free(type_s); - if (rc < 0) { - ssh_buffer_free(buffer); - return NULL; - } - - type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); - if (type_s == NULL) { - ssh_buffer_free(buffer); - return NULL; - } - - rc = buffer_add_ssh_string(buffer, type_s); - ssh_string_free(type_s); - if (rc < 0) { - ssh_buffer_free(buffer); - return NULL; - } - - e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)); - if (e == NULL) { - ssh_buffer_free(buffer); - return NULL; - } - - rc = buffer_add_ssh_string(buffer, e); - if (rc < 0) { - goto fail; - } - - ssh_string_burn(e); - ssh_string_free(e); - e = NULL; - - break; -#endif - case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_public_key_to_blob(buffer, key); - if (rc == SSH_ERROR){ - goto fail; - } - break; - case SSH_KEYTYPE_UNKNOWN: - default: - goto fail; - } - - str = ssh_string_new(buffer_get_rest_len(buffer)); - if (str == NULL) { - goto fail; - } - - rc = ssh_string_fill(str, buffer_get_rest(buffer), buffer_get_rest_len(buffer)); - if (rc < 0) { - goto fail; - } - ssh_buffer_free(buffer); - - return str; -fail: - ssh_buffer_free(buffer); - ssh_string_burn(str); - ssh_string_free(str); - ssh_string_burn(e); - ssh_string_free(e); - ssh_string_burn(p); - ssh_string_free(p); - ssh_string_burn(g); - ssh_string_free(g); - ssh_string_burn(q); - ssh_string_free(q); - ssh_string_burn(n); - ssh_string_free(n); - - return NULL; -} - -int pki_export_pubkey_rsa1(const ssh_key key, - const char *host, - char *rsa1, - size_t rsa1_len) -{ - char *e; - char *n; - int rsa_size = RSA_size(key->rsa); - - e = bignum_bn2dec(key->rsa->e); - if (e == NULL) { - return SSH_ERROR; - } - - n = bignum_bn2dec(key->rsa->n); - if (n == NULL) { - OPENSSL_free(e); - return SSH_ERROR; - } - - snprintf(rsa1, rsa1_len, - "%s %d %s %s\n", - host, rsa_size << 3, e, n); - OPENSSL_free(e); - OPENSSL_free(n); - - return SSH_OK; -} - -/** - * @internal - * - * @brief Compute a digital signature. - * - * @param[in] digest The message digest. - * - * @param[in] dlen The length of the digest. - * - * @param[in] privkey The private rsa key to use for signing. - * - * @return A newly allocated rsa sig blob or NULL on error. - */ -static ssh_string _RSA_do_sign(const unsigned char *digest, - int dlen, - RSA *privkey) -{ - ssh_string sig_blob; - unsigned char *sig; - unsigned int slen; - int ok; - - sig = malloc(RSA_size(privkey)); - if (sig == NULL) { - return NULL; - } - - ok = RSA_sign(NID_sha1, digest, dlen, sig, &slen, privkey); - if (!ok) { - SAFE_FREE(sig); - return NULL; - } - - sig_blob = ssh_string_new(slen); - if (sig_blob == NULL) { - SAFE_FREE(sig); - return NULL; - } - - ssh_string_fill(sig_blob, sig, slen); - memset(sig, 'd', slen); - SAFE_FREE(sig); - - return sig_blob; -} - -static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) -{ - char buffer[40] = { 0 }; - ssh_string sig_blob = NULL; - - ssh_string r; - int r_len, r_offset_in, r_offset_out; - - ssh_string s; - int s_len, s_offset_in, s_offset_out; - - r = make_bignum_string(sig->dsa_sig->r); - if (r == NULL) { - return NULL; - } - - s = make_bignum_string(sig->dsa_sig->s); - if (s == NULL) { - ssh_string_free(r); - return NULL; - } - - r_len = ssh_string_len(r); - r_offset_in = (r_len > 20) ? (r_len - 20) : 0; - r_offset_out = (r_len < 20) ? (20 - r_len) : 0; - - s_len = ssh_string_len(s); - s_offset_in = (s_len > 20) ? (s_len - 20) : 0; - s_offset_out = (s_len < 20) ? (20 - s_len) : 0; - - memcpy(buffer + r_offset_out, - ((char *)ssh_string_data(r)) + r_offset_in, - r_len - r_offset_in); - memcpy(buffer + 20 + s_offset_out, - ((char *)ssh_string_data(s)) + s_offset_in, - s_len - s_offset_in); - - ssh_string_free(r); - ssh_string_free(s); - - sig_blob = ssh_string_new(40); - if (sig_blob == NULL) { - return NULL; - } - - ssh_string_fill(sig_blob, buffer, 40); - - return sig_blob; -} - -ssh_string pki_signature_to_blob(const ssh_signature sig) -{ - ssh_string sig_blob = NULL; - - switch(sig->type) { - case SSH_KEYTYPE_DSS: - sig_blob = pki_dsa_signature_to_blob(sig); - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - sig_blob = ssh_string_copy(sig->rsa_sig); - break; |