Blame src/pki_crypto.c

Packit Service 31306d
/*
Packit Service 31306d
 * pki_crypto.c - PKI infrastructure using OpenSSL
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2003-2009 by Aris Adamantiadis
Packit Service 31306d
 * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#ifndef _PKI_CRYPTO_H
Packit Service 31306d
#define _PKI_CRYPTO_H
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
Packit Service 31306d
#include <openssl/pem.h>
Packit Service 31306d
#include <openssl/dsa.h>
Packit Service 31306d
#include <openssl/err.h>
Packit Service 31306d
#include <openssl/rsa.h>
Packit Service 31306d
#include "libcrypto-compat.h"
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_EC_H
Packit Service 31306d
#include <openssl/ec.h>
Packit Service 31306d
#endif
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECDSA_H
Packit Service 31306d
#include <openssl/ecdsa.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#include "libssh/libssh.h"
Packit Service 31306d
#include "libssh/buffer.h"
Packit Service 31306d
#include "libssh/session.h"
Packit Service 31306d
#include "libssh/pki.h"
Packit Service 31306d
#include "libssh/pki_priv.h"
Packit Service 31306d
#include "libssh/bignum.h"
Packit Service 31306d
Packit Service 31306d
struct pem_get_password_struct {
Packit Service 31306d
    ssh_auth_callback fn;
Packit Service 31306d
    void *data;
Packit Service 31306d
};
Packit Service 31306d
Packit Service 31306d
static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
Packit Service 31306d
    struct pem_get_password_struct *pgp = userdata;
Packit Service 31306d
Packit Service 31306d
    (void) rwflag; /* unused */
Packit Service 31306d
Packit Service 31306d
    if (buf == NULL) {
Packit Service 31306d
        return 0;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    memset(buf, '\0', size);
Packit Service 31306d
    if (pgp) {
Packit Service 31306d
        int rc;
Packit Service 31306d
Packit Service 31306d
        rc = pgp->fn("Passphrase for private key:",
Packit Service 31306d
                     buf, size, 0, 0,
Packit Service 31306d
                     pgp->data);
Packit Service 31306d
        if (rc == 0) {
Packit Service 31306d
            return strlen(buf);
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
static int pki_key_ecdsa_to_nid(EC_KEY *k)
Packit Service 31306d
{
Packit Service 31306d
    const EC_GROUP *g = EC_KEY_get0_group(k);
Packit Service 31306d
    int nid;
Packit Service 31306d
Packit Service 31306d
    nid = EC_GROUP_get_curve_name(g);
Packit Service 31306d
    if (nid) {
Packit Service 31306d
        return nid;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k)
Packit Service 31306d
{
Packit Service 31306d
    int nid;
Packit Service 31306d
Packit Service 31306d
    nid = pki_key_ecdsa_to_nid(k);
Packit Service 31306d
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_X9_62_prime256v1:
Packit Service 31306d
            return SSH_KEYTYPE_ECDSA_P256;
Packit Service 31306d
        case NID_secp384r1:
Packit Service 31306d
            return SSH_KEYTYPE_ECDSA_P384;
Packit Service 31306d
        case NID_secp521r1:
Packit Service 31306d
            return SSH_KEYTYPE_ECDSA_P521;
Packit Service 31306d
        default:
Packit Service 31306d
            return SSH_KEYTYPE_UNKNOWN;
Packit Service 31306d
    }
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
const char *pki_key_ecdsa_nid_to_name(int nid)
Packit Service 31306d
{
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_X9_62_prime256v1:
Packit Service 31306d
            return "ecdsa-sha2-nistp256";
Packit Service 31306d
        case NID_secp384r1:
Packit Service 31306d
            return "ecdsa-sha2-nistp384";
Packit Service 31306d
        case NID_secp521r1:
Packit Service 31306d
            return "ecdsa-sha2-nistp521";
Packit Service 31306d
        default:
Packit Service 31306d
            break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return "unknown";
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static const char *pki_key_ecdsa_nid_to_char(int nid)
Packit Service 31306d
{
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_X9_62_prime256v1:
Packit Service 31306d
            return "nistp256";
Packit Service 31306d
        case NID_secp384r1:
Packit Service 31306d
            return "nistp384";
Packit Service 31306d
        case NID_secp521r1:
Packit Service 31306d
            return "nistp521";
Packit Service 31306d
        default:
Packit Service 31306d
            break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return "unknown";
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_ecdsa_nid_from_name(const char *name)
Packit Service 31306d
{
Packit Service 31306d
    if (strcmp(name, "nistp256") == 0) {
Packit Service 31306d
        return NID_X9_62_prime256v1;
Packit Service 31306d
    } else if (strcmp(name, "nistp384") == 0) {
Packit Service 31306d
        return NID_secp384r1;
Packit Service 31306d
    } else if (strcmp(name, "nistp521") == 0) {
Packit Service 31306d
        return NID_secp521r1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static ssh_string make_ecpoint_string(const EC_GROUP *g,
Packit Service 31306d
                                      const EC_POINT *p)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string s;
Packit Service 31306d
    size_t len;
Packit Service 31306d
Packit Service 31306d
    len = EC_POINT_point2oct(g,
Packit Service 31306d
                             p,
Packit Service 31306d
                             POINT_CONVERSION_UNCOMPRESSED,
Packit Service 31306d
                             NULL,
Packit Service 31306d
                             0,
Packit Service 31306d
                             NULL);
Packit Service 31306d
    if (len == 0) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    s = ssh_string_new(len);
Packit Service 31306d
    if (s == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    len = EC_POINT_point2oct(g,
Packit Service 31306d
                             p,
Packit Service 31306d
                             POINT_CONVERSION_UNCOMPRESSED,
Packit Service 31306d
                             ssh_string_data(s),
Packit Service 31306d
                             ssh_string_len(s),
Packit Service 31306d
                             NULL);
Packit Service 31306d
    if (len != ssh_string_len(s)) {
Packit Service 31306d
        SSH_STRING_FREE(s);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return s;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
Packit Service 31306d
{
Packit Service 31306d
    EC_POINT *p = NULL;
Packit Service 31306d
    const EC_GROUP *g = NULL;
Packit Service 31306d
    int ok;
Packit Service 31306d
    BIGNUM *bexp = NULL;
Packit Service 31306d
Packit Service 31306d
    key->ecdsa_nid = nid;
Packit Service 31306d
    key->type_c = pki_key_ecdsa_nid_to_name(nid);
Packit Service 31306d
Packit Service 31306d
    key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    g = EC_KEY_get0_group(key->ecdsa);
Packit Service 31306d
Packit Service 31306d
    p = EC_POINT_new(g);
Packit Service 31306d
    if (p == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ok = EC_POINT_oct2point(g,
Packit Service 31306d
                            p,
Packit Service 31306d
                            ssh_string_data(e),
Packit Service 31306d
                            ssh_string_len(e),
Packit Service 31306d
                            NULL);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        EC_POINT_free(p);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* EC_KEY_set_public_key duplicates p */
Packit Service 31306d
    ok = EC_KEY_set_public_key(key->ecdsa, p);
Packit Service 31306d
    EC_POINT_free(p);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    bexp = ssh_make_string_bn(exp);
Packit Service 31306d
    if (bexp == NULL) {
Packit Service 31306d
        EC_KEY_free(key->ecdsa);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
    /* EC_KEY_set_private_key duplicates exp */
Packit Service 31306d
    ok = EC_KEY_set_private_key(key->ecdsa, bexp);
Packit Service 31306d
    BN_free(bexp);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        EC_KEY_free(key->ecdsa);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
Packit Service 31306d
{
Packit Service 31306d
    EC_POINT *p = NULL;
Packit Service 31306d
    const EC_GROUP *g = NULL;
Packit Service 31306d
    int ok;
Packit Service 31306d
Packit Service 31306d
    key->ecdsa_nid = nid;
Packit Service 31306d
    key->type_c = pki_key_ecdsa_nid_to_name(nid);
Packit Service 31306d
Packit Service 31306d
    key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    g = EC_KEY_get0_group(key->ecdsa);
Packit Service 31306d
Packit Service 31306d
    p = EC_POINT_new(g);
Packit Service 31306d
    if (p == NULL) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ok = EC_POINT_oct2point(g,
Packit Service 31306d
                            p,
Packit Service 31306d
                            ssh_string_data(e),
Packit Service 31306d
                            ssh_string_len(e),
Packit Service 31306d
                            NULL);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        EC_POINT_free(p);
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* EC_KEY_set_public_key duplicates p */
Packit Service 31306d
    ok = EC_KEY_set_public_key(key->ecdsa, p);
Packit Service 31306d
    EC_POINT_free(p);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        return -1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
ssh_key pki_key_dup(const ssh_key key, int demote)
Packit Service 31306d
{
Packit Service 31306d
    ssh_key new;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    new = ssh_key_new();
Packit Service 31306d
    if (new == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    new->type = key->type;
Packit Service 31306d
    new->type_c = key->type_c;
Packit Service 31306d
    if (demote) {
Packit Service 31306d
        new->flags = SSH_KEY_FLAG_PUBLIC;
Packit Service 31306d
    } else {
Packit Service 31306d
        new->flags = key->flags;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (key->type) {
Packit Service 31306d
    case SSH_KEYTYPE_DSS: {
Packit Service 31306d
        const BIGNUM *p = NULL, *q = NULL, *g = NULL,
Packit Service 31306d
          *pub_key = NULL, *priv_key = NULL;
Packit Service 31306d
        BIGNUM *np, *nq, *ng, *npub_key, *npriv_key;
Packit Service 31306d
        new->dsa = DSA_new();
Packit Service 31306d
        if (new->dsa == NULL) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /*
Packit Service 31306d
         * p        = public prime number
Packit Service 31306d
         * q        = public 160-bit subprime, q | p-1
Packit Service 31306d
         * g        = public generator of subgroup
Packit Service 31306d
         * pub_key  = public key y = g^x
Packit Service 31306d
         * priv_key = private key x
Packit Service 31306d
         */
Packit Service 31306d
        DSA_get0_pqg(key->dsa, &p, &q, &g);
Packit Service 31306d
        np = BN_dup(p);
Packit Service 31306d
        nq = BN_dup(q);
Packit Service 31306d
        ng = BN_dup(g);
Packit Service 31306d
        if (np == NULL || nq == NULL || ng == NULL) {
Packit Service 31306d
            BN_free(np);
Packit Service 31306d
            BN_free(nq);
Packit Service 31306d
            BN_free(ng);
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* Memory management of np, nq and ng is transferred to DSA object */
Packit Service 31306d
        rc = DSA_set0_pqg(new->dsa, np, nq, ng);
Packit Service 31306d
        if (rc == 0) {
Packit Service 31306d
            BN_free(np);
Packit Service 31306d
            BN_free(nq);
Packit Service 31306d
            BN_free(ng);
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        DSA_get0_key(key->dsa, &pub_key, &priv_key);
Packit Service 31306d
        npub_key = BN_dup(pub_key);
Packit Service 31306d
        if (npub_key == NULL) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* Memory management of npubkey is transferred to DSA object */
Packit Service 31306d
        rc = DSA_set0_key(new->dsa, npub_key, NULL);
Packit Service 31306d
        if (rc == 0) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
Packit Service 31306d
            npriv_key = BN_dup(priv_key);
Packit Service 31306d
            if (npriv_key == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            /* Memory management of npriv_key is transferred to DSA object */
Packit Service 31306d
            rc = DSA_set0_key(new->dsa, NULL, npriv_key);
Packit Service 31306d
            if (rc == 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        break;
Packit Service 31306d
    }
Packit Service 31306d
    case SSH_KEYTYPE_RSA:
Packit Service 31306d
    case SSH_KEYTYPE_RSA1: {
Packit Service 31306d
        const BIGNUM *n = NULL, *e = NULL, *d = NULL;
Packit Service 31306d
        BIGNUM *nn, *ne, *nd;
Packit Service 31306d
        new->rsa = RSA_new();
Packit Service 31306d
        if (new->rsa == NULL) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /*
Packit Service 31306d
         * n    = public modulus
Packit Service 31306d
         * e    = public exponent
Packit Service 31306d
         * d    = private exponent
Packit Service 31306d
         * p    = secret prime factor
Packit Service 31306d
         * q    = secret prime factor
Packit Service 31306d
         * dmp1 = d mod (p-1)
Packit Service 31306d
         * dmq1 = d mod (q-1)
Packit Service 31306d
         * iqmp = q^-1 mod p
Packit Service 31306d
         */
Packit Service 31306d
        RSA_get0_key(key->rsa, &n, &e, &d);
Packit Service 31306d
        nn = BN_dup(n);
Packit Service 31306d
        ne = BN_dup(e);
Packit Service 31306d
        if (nn == NULL || ne == NULL) {
Packit Service 31306d
            BN_free(nn);
Packit Service 31306d
            BN_free(ne);
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* Memory management of nn and ne is transferred to RSA object */
Packit Service 31306d
        rc = RSA_set0_key(new->rsa, nn, ne, NULL);
Packit Service 31306d
        if (rc == 0) {
Packit Service 31306d
            BN_free(nn);
Packit Service 31306d
            BN_free(ne);
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
Packit Service 31306d
            const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL,
Packit Service 31306d
              *dmq1 = NULL, *iqmp = NULL;
Packit Service 31306d
            BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp;
Packit Service 31306d
Packit Service 31306d
            nd = BN_dup(d);
Packit Service 31306d
            if (nd == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            /* Memory management of nd is transferred to RSA object */
Packit Service 31306d
            rc = RSA_set0_key(new->rsa, NULL, NULL, nd);
Packit Service 31306d
            if (rc == 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the
Packit Service 31306d
             * RSA operations are much faster when these values are available.
Packit Service 31306d
             */
Packit Service 31306d
            RSA_get0_factors(key->rsa, &p, &q);
Packit Service 31306d
            if (p != NULL && q != NULL) { /* need to set both of them */
Packit Service 31306d
                np = BN_dup(p);
Packit Service 31306d
                nq = BN_dup(q);
Packit Service 31306d
                if (np == NULL || nq == NULL) {
Packit Service 31306d
                    BN_free(np);
Packit Service 31306d
                    BN_free(nq);
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                /* Memory management of np and nq is transferred to RSA object */
Packit Service 31306d
                rc = RSA_set0_factors(new->rsa, np, nq);
Packit Service 31306d
                if (rc == 0) {
Packit Service 31306d
                    BN_free(np);
Packit Service 31306d
                    BN_free(nq);
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp);
Packit Service 31306d
            if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) {
Packit Service 31306d
                ndmp1 = BN_dup(dmp1);
Packit Service 31306d
                ndmq1 = BN_dup(dmq1);
Packit Service 31306d
                niqmp = BN_dup(iqmp);
Packit Service 31306d
                if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) {
Packit Service 31306d
                    BN_free(ndmp1);
Packit Service 31306d
                    BN_free(ndmq1);
Packit Service 31306d
                    BN_free(niqmp);
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                /* Memory management of ndmp1, ndmq1 and niqmp is transferred
Packit Service 31306d
                 * to RSA object */
Packit Service 31306d
                rc =  RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
Packit Service 31306d
                if (rc == 0) {
Packit Service 31306d
                    BN_free(ndmp1);
Packit Service 31306d
                    BN_free(ndmq1);
Packit Service 31306d
                    BN_free(niqmp);
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        break;
Packit Service 31306d
    }
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
        new->ecdsa_nid = key->ecdsa_nid;
Packit Service 31306d
Packit Service 31306d
        /* privkey -> pubkey */
Packit Service 31306d
        if (demote && ssh_key_is_private(key)) {
Packit Service 31306d
            const EC_POINT *p;
Packit Service 31306d
            int ok;
Packit Service 31306d
Packit Service 31306d
            new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
Packit Service 31306d
            if (new->ecdsa == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            p = EC_KEY_get0_public_key(key->ecdsa);
Packit Service 31306d
            if (p == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            ok = EC_KEY_set_public_key(new->ecdsa, p);
Packit Service 31306d
            if (!ok) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
        } else {
Packit Service 31306d
            new->ecdsa = EC_KEY_dup(key->ecdsa);
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
#endif
Packit Service 31306d
    case SSH_KEYTYPE_ED25519:
Packit Service 31306d
        rc = pki_ed25519_key_dup(new, key);
Packit Service 31306d
        if (rc != SSH_OK) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
    default:
Packit Service 31306d
        ssh_key_free(new);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return new;
Packit Service 31306d
fail:
Packit Service 31306d
    ssh_key_free(new);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_generate_rsa(ssh_key key, int parameter){
Packit Service 31306d
	BIGNUM *e;
Packit Service 31306d
	int rc;
Packit Service 31306d
Packit Service 31306d
	e = BN_new();
Packit Service 31306d
	key->rsa = RSA_new();
Packit Service 31306d
Packit Service 31306d
	BN_set_word(e, 65537);
Packit Service 31306d
	rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL);
Packit Service 31306d
Packit Service 31306d
	BN_free(e);
Packit Service 31306d
Packit Service 31306d
	if (rc <= 0 || key->rsa == NULL)
Packit Service 31306d
		return SSH_ERROR;
Packit Service 31306d
	return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_generate_dss(ssh_key key, int parameter){
Packit Service 31306d
    int rc;
Packit Service 31306d
#if OPENSSL_VERSION_NUMBER > 0x00908000L
Packit Service 31306d
    key->dsa = DSA_new();
Packit Service 31306d
    if (key->dsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    rc = DSA_generate_parameters_ex(key->dsa,
Packit Service 31306d
                                    parameter,
Packit Service 31306d
                                    NULL,  /* seed */
Packit Service 31306d
                                    0,     /* seed_len */
Packit Service 31306d
                                    NULL,  /* counter_ret */
Packit Service 31306d
                                    NULL,  /* h_ret */
Packit Service 31306d
                                    NULL); /* cb */
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        DSA_free(key->dsa);
Packit Service 31306d
        key->dsa = NULL;
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
#else
Packit Service 31306d
    key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL,
Packit Service 31306d
            NULL, NULL);
Packit Service 31306d
    if(key->dsa == NULL){
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
    rc = DSA_generate_key(key->dsa);
Packit Service 31306d
    if (rc != 1){
Packit Service 31306d
        DSA_free(key->dsa);
Packit Service 31306d
        key->dsa=NULL;
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
int pki_key_generate_ecdsa(ssh_key key, int parameter) {
Packit Service 31306d
    int ok;
Packit Service 31306d
Packit Service 31306d
    switch (parameter) {
Packit Service 31306d
        case 384:
Packit Service 31306d
            key->ecdsa_nid = NID_secp384r1;
Packit Service 31306d
            key->type = SSH_KEYTYPE_ECDSA_P384;
Packit Service 31306d
            break;
Packit Service 31306d
        case 521:
Packit Service 31306d
            key->ecdsa_nid = NID_secp521r1;
Packit Service 31306d
            key->type = SSH_KEYTYPE_ECDSA_P521;
Packit Service 31306d
            break;
Packit Service 31306d
        case 256:
Packit Service 31306d
            key->ecdsa_nid = NID_X9_62_prime256v1;
Packit Service 31306d
            key->type = SSH_KEYTYPE_ECDSA_P256;
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Invalid parameter %d for ECDSA key "
Packit Service 31306d
                    "generation", parameter);
Packit Service 31306d
            return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ok = EC_KEY_generate_key(key->ecdsa);
Packit Service 31306d
    if (!ok) {
Packit Service 31306d
        EC_KEY_free(key->ecdsa);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE);
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
int pki_key_compare(const ssh_key k1,
Packit Service 31306d
                    const ssh_key k2,
Packit Service 31306d
                    enum ssh_keycmp_e what)
Packit Service 31306d
{
Packit Service 31306d
    switch (k1->type) {
Packit Service 31306d
        case SSH_KEYTYPE_DSS: {
Packit Service 31306d
            const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2,
Packit Service 31306d
                *pub_key1, *pub_key2, *priv_key1, *priv_key2;
Packit Service 31306d
            if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            DSA_get0_pqg(k1->dsa, &p1, &q1, &g1;;
Packit Service 31306d
            DSA_get0_pqg(k2->dsa, &p2, &q2, &g2;;
Packit Service 31306d
            if (bignum_cmp(p1, p2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            if (bignum_cmp(q1, q2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            if (bignum_cmp(g1, g2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            DSA_get0_key(k1->dsa, &pub_key1, &priv_key1);
Packit Service 31306d
            DSA_get0_key(k2->dsa, &pub_key2, &priv_key2);
Packit Service 31306d
            if (bignum_cmp(pub_key1, pub_key2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (what == SSH_KEY_CMP_PRIVATE) {
Packit Service 31306d
                if (bignum_cmp(priv_key1, priv_key2) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA1: {
Packit Service 31306d
            const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2;
Packit Service 31306d
            if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            RSA_get0_key(k1->rsa, &n1, &e1, NULL);
Packit Service 31306d
            RSA_get0_key(k2->rsa, &n2, &e2, NULL);
Packit Service 31306d
            if (bignum_cmp(e1, e2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            if (bignum_cmp(n1, n2) != 0) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (what == SSH_KEY_CMP_PRIVATE) {
Packit Service 31306d
                RSA_get0_factors(k1->rsa, &p1, &q1;;
Packit Service 31306d
                RSA_get0_factors(k2->rsa, &p2, &q2;;
Packit Service 31306d
                if (bignum_cmp(p1, p2) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                if (bignum_cmp(q1, q2) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
            {
Packit Service 31306d
                const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa);
Packit Service 31306d
                const EC_POINT *p2 = EC_KEY_get0_public_key(k2->ecdsa);
Packit Service 31306d
                const EC_GROUP *g1 = EC_KEY_get0_group(k1->ecdsa);
Packit Service 31306d
                const EC_GROUP *g2 = EC_KEY_get0_group(k2->ecdsa);
Packit Service 31306d
Packit Service 31306d
                if (p1 == NULL || p2 == NULL) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                if (EC_GROUP_cmp(g1, g2, NULL) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                if (EC_POINT_cmp(g1, p1, p2, NULL) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                if (what == SSH_KEY_CMP_PRIVATE) {
Packit Service 31306d
                    if (bignum_cmp(EC_KEY_get0_private_key(k1->ecdsa),
Packit Service 31306d
                                   EC_KEY_get0_private_key(k2->ecdsa))) {
Packit Service 31306d
                        return 1;
Packit Service 31306d
                    }
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                break;
Packit Service 31306d
            }
Packit Service 31306d
#endif
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            /* ed25519 keys handled globaly */
Packit Service 31306d
        case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
        default:
Packit Service 31306d
            return 1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
ssh_string pki_private_key_to_pem(const ssh_key key,
Packit Service 31306d
                                  const char *passphrase,
Packit Service 31306d
                                  ssh_auth_callback auth_fn,
Packit Service 31306d
                                  void *auth_data)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string blob = NULL;
Packit Service 31306d
    BUF_MEM *buf = NULL;
Packit Service 31306d
    BIO *mem = NULL;
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    mem = BIO_new(BIO_s_mem());
Packit Service 31306d
    if (mem == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (key->type) {
Packit Service 31306d
        case SSH_KEYTYPE_DSS:
Packit Service 31306d
            pkey = EVP_PKEY_new();
Packit Service 31306d
            if (pkey == NULL) {
Packit Service 31306d
                goto err;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = EVP_PKEY_set1_DSA(pkey, key->dsa);
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA1:
Packit Service 31306d
            pkey = EVP_PKEY_new();
Packit Service 31306d
            if (pkey == NULL) {
Packit Service 31306d
                goto err;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = EVP_PKEY_set1_RSA(pkey, key->rsa);
Packit Service 31306d
            break;
Packit Service 31306d
#ifdef HAVE_ECC
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
            pkey = EVP_PKEY_new();
Packit Service 31306d
            if (pkey == NULL) {
Packit Service 31306d
                goto err;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
Packit Service 31306d
            break;
Packit Service 31306d
#endif
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ED25519
Packit Service 31306d
            /* In OpenSSL, the input is the private key seed only, which means
Packit Service 31306d
             * the first half of the SSH private key (the second half is the
Packit Service 31306d
             * public key) */
Packit Service 31306d
            pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
Packit Service 31306d
                    (const uint8_t *)key->ed25519_privkey,
Packit Service 31306d
                    ED25519_KEY_LEN);
Packit Service 31306d
            if (pkey == NULL) {
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                        "Failed to create ed25519 EVP_PKEY: %s",
Packit Service 31306d
                        ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
                goto err;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            /* Mark the operation as successful as for the other key types */
Packit Service 31306d
            rc = 1;
Packit Service 31306d
            break;
Packit Service 31306d
#else
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519");
Packit Service 31306d
            goto err;
Packit Service 31306d
#endif
Packit Service 31306d
        case SSH_KEYTYPE_DSS_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_RSA_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ED25519_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
        default:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type);
Packit Service 31306d
            goto err;
Packit Service 31306d
    }
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Failed to initialize EVP_PKEY structure");
Packit Service 31306d
        goto err;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (passphrase == NULL) {
Packit Service 31306d
        struct pem_get_password_struct pgp = { auth_fn, auth_data };
Packit Service 31306d
Packit Service 31306d
        rc = PEM_write_bio_PrivateKey(mem,
Packit Service 31306d
                                      pkey,
Packit Service 31306d
                                      NULL, /* cipher */
Packit Service 31306d
                                      NULL, /* kstr */
Packit Service 31306d
                                      0, /* klen */
Packit Service 31306d
                                      pem_get_password,
Packit Service 31306d
                                      &pgp);
Packit Service 31306d
    } else {
Packit Service 31306d
        rc = PEM_write_bio_PrivateKey(mem,
Packit Service 31306d
                                      pkey,
Packit Service 31306d
                                      EVP_aes_128_cbc(),
Packit Service 31306d
                                      NULL, /* kstr */
Packit Service 31306d
                                      0, /* klen */
Packit Service 31306d
                                      NULL, /* auth_fn */
Packit Service 31306d
                                      (void*) passphrase);
Packit Service 31306d
    }
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
    pkey = NULL;
Packit Service 31306d
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        goto err;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    BIO_get_mem_ptr(mem, &buf;;
Packit Service 31306d
Packit Service 31306d
    blob = ssh_string_new(buf->length);
Packit Service 31306d
    if (blob == NULL) {
Packit Service 31306d
        goto err;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_string_fill(blob, buf->data, buf->length);
Packit Service 31306d
    BIO_free(mem);
Packit Service 31306d
Packit Service 31306d
    return blob;
Packit Service 31306d
Packit Service 31306d
err:
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
    BIO_free(mem);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
ssh_key pki_private_key_from_base64(const char *b64_key,
Packit Service 31306d
                                    const char *passphrase,
Packit Service 31306d
                                    ssh_auth_callback auth_fn,
Packit Service 31306d
                                    void *auth_data)
Packit Service 31306d
{
Packit Service 31306d
    BIO *mem = NULL;
Packit Service 31306d
    DSA *dsa = NULL;
Packit Service 31306d
    RSA *rsa = NULL;
Packit Service 31306d
#ifdef HAVE_OPENSSL_ED25519
Packit Service 31306d
    uint8_t *ed25519 = NULL;
Packit Service 31306d
#else
Packit Service 31306d
    ed25519_privkey *ed25519 = NULL;
Packit Service 31306d
#endif
Packit Service 31306d
    ssh_key key = NULL;
Packit Service 31306d
    enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
    EC_KEY *ecdsa = NULL;
Packit Service 31306d
#else
Packit Service 31306d
    void *ecdsa = NULL;
Packit Service 31306d
#endif
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
Packit Service 31306d
    mem = BIO_new_mem_buf((void*)b64_key, -1);
Packit Service 31306d
Packit Service 31306d
    if (passphrase == NULL) {
Packit Service 31306d
        if (auth_fn) {
Packit Service 31306d
            struct pem_get_password_struct pgp = { auth_fn, auth_data };
Packit Service 31306d
Packit Service 31306d
            pkey = PEM_read_bio_PrivateKey(mem, NULL, pem_get_password, &pgp);
Packit Service 31306d
        } else {
Packit Service 31306d
            /* openssl uses its own callback to get the passphrase here */
Packit Service 31306d
            pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, (void *) passphrase);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    BIO_free(mem);
Packit Service 31306d
Packit Service 31306d
    if (pkey == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                "Parsing private key: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    switch (EVP_PKEY_base_id(pkey)) {
Packit Service 31306d
    case EVP_PKEY_DSA:
Packit Service 31306d
        dsa = EVP_PKEY_get1_DSA(pkey);
Packit Service 31306d
        if (dsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                    "Parsing private key: %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(),NULL));
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
        type = SSH_KEYTYPE_DSS;
Packit Service 31306d
        break;
Packit Service 31306d
    case EVP_PKEY_RSA:
Packit Service 31306d
        rsa = EVP_PKEY_get1_RSA(pkey);
Packit Service 31306d
        if (rsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                    "Parsing private key: %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(),NULL));
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
        type = SSH_KEYTYPE_RSA;
Packit Service 31306d
        break;
Packit Service 31306d
    case EVP_PKEY_EC:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
        ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
Packit Service 31306d
        if (ecdsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                    "Parsing private key: %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* pki_privatekey_type_from_string always returns P256 for ECDSA
Packit Service 31306d
         * keys, so we need to figure out the correct type here */
Packit Service 31306d
        type = pki_key_ecdsa_to_key_type(ecdsa);
Packit Service 31306d
        if (type == SSH_KEYTYPE_UNKNOWN) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Invalid private key.");
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        break;
Packit Service 31306d
#endif
Packit Service 31306d
#ifdef HAVE_OPENSSL_ED25519
Packit Service 31306d
    case EVP_PKEY_ED25519:
Packit Service 31306d
    {
Packit Service 31306d
        size_t key_len;
Packit Service 31306d
        int evp_rc = 0;
Packit Service 31306d
Packit Service 31306d
        /* Get the key length */
Packit Service 31306d
        evp_rc = EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len);
Packit Service 31306d
        if (evp_rc != 1) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                    "Failed to get ed25519 raw private key length:  %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        if (key_len != ED25519_KEY_LEN) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        ed25519 = malloc(key_len);
Packit Service 31306d
        if (ed25519 == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Out of memory");
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)ed25519,
Packit Service 31306d
                                              &key_len);
Packit Service 31306d
        if (evp_rc != 1) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                    "Failed to get ed25519 raw private key:  %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
        type = SSH_KEYTYPE_ED25519;
Packit Service 31306d
    }
Packit Service 31306d
    break;
Packit Service 31306d
#endif
Packit Service 31306d
    default:
Packit Service 31306d
        EVP_PKEY_free(pkey);
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
Packit Service 31306d
                EVP_PKEY_base_id(pkey));
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
Packit Service 31306d
    key = ssh_key_new();
Packit Service 31306d
    if (key == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    key->type = type;
Packit Service 31306d
    key->type_c = ssh_key_type_to_char(type);
Packit Service 31306d
    key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
Packit Service 31306d
    key->dsa = dsa;
Packit Service 31306d
    key->rsa = rsa;
Packit Service 31306d
    key->ecdsa = ecdsa;
Packit Service 31306d
    key->ed25519_privkey = ed25519;
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
    if (is_ecdsa_key_type(key->type)) {
Packit Service 31306d
        key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    return key;
Packit Service 31306d
fail:
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
    ssh_key_free(key);
Packit Service 31306d
    DSA_free(dsa);
Packit Service 31306d
    RSA_free(rsa);
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
    EC_KEY_free(ecdsa);
Packit Service 31306d
#endif
Packit Service 31306d
#ifdef HAVE_OPENSSL_ED25519
Packit Service 31306d
    SAFE_FREE(ed25519);
Packit Service 31306d
#endif
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_privkey_build_dss(ssh_key key,
Packit Service 31306d
                          ssh_string p,
Packit Service 31306d
                          ssh_string q,
Packit Service 31306d
                          ssh_string g,
Packit Service 31306d
                          ssh_string pubkey,
Packit Service 31306d
                          ssh_string privkey)
Packit Service 31306d
{
Packit Service 31306d
    int rc;
Packit Service 31306d
    BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key;
Packit Service 31306d
Packit Service 31306d
    key->dsa = DSA_new();
Packit Service 31306d
    if (key->dsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    bp = ssh_make_string_bn(p);
Packit Service 31306d
    bq = ssh_make_string_bn(q);
Packit Service 31306d
    bg = ssh_make_string_bn(g);
Packit Service 31306d
    bpub_key = ssh_make_string_bn(pubkey);
Packit Service 31306d
    bpriv_key = ssh_make_string_bn(privkey);
Packit Service 31306d
    if (bp == NULL || bq == NULL ||
Packit Service 31306d
        bg == NULL || bpub_key == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of bp, qq and bg is transferred to DSA object */
Packit Service 31306d
    rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of bpub_key and bpriv_key is transferred to DSA object */
Packit Service 31306d
    rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
fail:
Packit Service 31306d
    DSA_free(key->dsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_pubkey_build_dss(ssh_key key,
Packit Service 31306d
                         ssh_string p,
Packit Service 31306d
                         ssh_string q,
Packit Service 31306d
                         ssh_string g,
Packit Service 31306d
                         ssh_string pubkey) {
Packit Service 31306d
    int rc;
Packit Service 31306d
    BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL;
Packit Service 31306d
Packit Service 31306d
    key->dsa = DSA_new();
Packit Service 31306d
    if (key->dsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    bp = ssh_make_string_bn(p);
Packit Service 31306d
    bq = ssh_make_string_bn(q);
Packit Service 31306d
    bg = ssh_make_string_bn(g);
Packit Service 31306d
    bpub_key = ssh_make_string_bn(pubkey);
Packit Service 31306d
    if (bp == NULL || bq == NULL ||
Packit Service 31306d
        bg == NULL || bpub_key == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of bp, bq and bg is transferred to DSA object */
Packit Service 31306d
    rc = DSA_set0_pqg(key->dsa, bp, bq, bg);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of npub_key is transferred to DSA object */
Packit Service 31306d
    rc = DSA_set0_key(key->dsa, bpub_key, NULL);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
fail:
Packit Service 31306d
    DSA_free(key->dsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_privkey_build_rsa(ssh_key key,
Packit Service 31306d
                          ssh_string n,
Packit Service 31306d
                          ssh_string e,
Packit Service 31306d
                          ssh_string d,
Packit Service 31306d
                          UNUSED_PARAM(ssh_string iqmp),
Packit Service 31306d
                          ssh_string p,
Packit Service 31306d
                          ssh_string q)
Packit Service 31306d
{
Packit Service 31306d
    int rc;
Packit Service 31306d
    BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq;
Packit Service 31306d
Packit Service 31306d
    key->rsa = RSA_new();
Packit Service 31306d
    if (key->rsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    bn = ssh_make_string_bn(n);
Packit Service 31306d
    be = ssh_make_string_bn(e);
Packit Service 31306d
    bd = ssh_make_string_bn(d);
Packit Service 31306d
    /*biqmp = ssh_make_string_bn(iqmp);*/
Packit Service 31306d
    bp = ssh_make_string_bn(p);
Packit Service 31306d
    bq = ssh_make_string_bn(q);
Packit Service 31306d
    if (be == NULL || bn == NULL || bd == NULL ||
Packit Service 31306d
        /*biqmp == NULL ||*/ bp == NULL || bq == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of be, bn and bd is transferred to RSA object */
Packit Service 31306d
    rc = RSA_set0_key(key->rsa, bn, be, bd);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of bp and bq is transferred to RSA object */
Packit Service 31306d
    rc = RSA_set0_factors(key->rsa, bp, bq);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA
Packit Service 31306d
     * operations are much faster when these values are available.
Packit Service 31306d
     * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html
Packit Service 31306d
     */
Packit Service 31306d
    /* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL);
Packit Service 31306d
    TODO calculate missing crt_params */
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
fail:
Packit Service 31306d
    RSA_free(key->rsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_pubkey_build_rsa(ssh_key key,
Packit Service 31306d
                         ssh_string e,
Packit Service 31306d
                         ssh_string n) {
Packit Service 31306d
    int rc;
Packit Service 31306d
    BIGNUM *be = NULL, *bn = NULL;
Packit Service 31306d
Packit Service 31306d
    key->rsa = RSA_new();
Packit Service 31306d
    if (key->rsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    be = ssh_make_string_bn(e);
Packit Service 31306d
    bn = ssh_make_string_bn(n);
Packit Service 31306d
    if (be == NULL || bn == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of bn and be is transferred to RSA object */
Packit Service 31306d
    rc = RSA_set0_key(key->rsa, bn, be, NULL);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
fail:
Packit Service 31306d
    RSA_free(key->rsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
ssh_string pki_publickey_to_blob(const ssh_key key)
Packit Service 31306d
{
Packit Service 31306d
    ssh_buffer buffer;
Packit Service 31306d
    ssh_string type_s;
Packit Service 31306d
    ssh_string str = NULL;
Packit Service 31306d
    ssh_string e = NULL;
Packit Service 31306d
    ssh_string n = NULL;
Packit Service 31306d
    ssh_string p = NULL;
Packit Service 31306d
    ssh_string g = NULL;
Packit Service 31306d
    ssh_string q = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    buffer = ssh_buffer_new();
Packit Service 31306d
    if (buffer == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (key->cert != NULL) {
Packit Service 31306d
        rc = ssh_buffer_add_buffer(buffer, key->cert);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            SSH_BUFFER_FREE(buffer);
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
        goto makestring;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    type_s = ssh_string_from_char(key->type_c);
Packit Service 31306d
    if (type_s == NULL) {
Packit Service 31306d
        SSH_BUFFER_FREE(buffer);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_add_ssh_string(buffer, type_s);
Packit Service 31306d
    SSH_STRING_FREE(type_s);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        SSH_BUFFER_FREE(buffer);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (key->type) {
Packit Service 31306d
        case SSH_KEYTYPE_DSS: {
Packit Service 31306d
            const BIGNUM *bp, *bq, *bg, *bpub_key;
Packit Service 31306d
            DSA_get0_pqg(key->dsa, &bp, &bq, &bg;;
Packit Service 31306d
            p = ssh_make_bignum_string((BIGNUM *)bp);
Packit Service 31306d
            if (p == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            q = ssh_make_bignum_string((BIGNUM *)bq);
Packit Service 31306d
            if (q == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            g = ssh_make_bignum_string((BIGNUM *)bg);
Packit Service 31306d
            if (g == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            DSA_get0_key(key->dsa, &bpub_key, NULL);
Packit Service 31306d
            n = ssh_make_bignum_string((BIGNUM *)bpub_key);
Packit Service 31306d
            if (n == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, p) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, q) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, g) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            ssh_string_burn(p);
Packit Service 31306d
            SSH_STRING_FREE(p);
Packit Service 31306d
            p = NULL;
Packit Service 31306d
            ssh_string_burn(g);
Packit Service 31306d
            SSH_STRING_FREE(g);
Packit Service 31306d
            g = NULL;
Packit Service 31306d
            ssh_string_burn(q);
Packit Service 31306d
            SSH_STRING_FREE(q);
Packit Service 31306d
            q = NULL;
Packit Service 31306d
            ssh_string_burn(n);
Packit Service 31306d
            SSH_STRING_FREE(n);
Packit Service 31306d
            n = NULL;
Packit Service 31306d
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA1: {
Packit Service 31306d
            const BIGNUM *be, *bn;
Packit Service 31306d
            RSA_get0_key(key->rsa, &bn, &be, NULL);
Packit Service 31306d
            e = ssh_make_bignum_string((BIGNUM *)be);
Packit Service 31306d
            if (e == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            n = ssh_make_bignum_string((BIGNUM *)bn);
Packit Service 31306d
            if (n == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            if (ssh_buffer_add_ssh_string(buffer, n) < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            ssh_string_burn(e);
Packit Service 31306d
            SSH_STRING_FREE(e);
Packit Service 31306d
            e = NULL;
Packit Service 31306d
            ssh_string_burn(n);
Packit Service 31306d
            SSH_STRING_FREE(n);
Packit Service 31306d
            n = NULL;
Packit Service 31306d
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            rc = pki_ed25519_public_key_to_blob(buffer, key);
Packit Service 31306d
            if (rc == SSH_ERROR){
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
            type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
Packit Service 31306d
            if (type_s == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(buffer);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_buffer_add_ssh_string(buffer, type_s);
Packit Service 31306d
            SSH_STRING_FREE(type_s);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                SSH_BUFFER_FREE(buffer);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa),
Packit Service 31306d
                                    EC_KEY_get0_public_key(key->ecdsa));
Packit Service 31306d
            if (e == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(buffer);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_buffer_add_ssh_string(buffer, e);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            ssh_string_burn(e);
Packit Service 31306d
            SSH_STRING_FREE(e);
Packit Service 31306d
            e = NULL;
Packit Service 31306d
Packit Service 31306d
            break;
Packit Service 31306d
#endif
Packit Service 31306d
        case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
        default:
Packit Service 31306d
            goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
makestring:
Packit Service 31306d
    str = ssh_string_new(ssh_buffer_get_len(buffer));
Packit Service 31306d
    if (str == NULL) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_string_fill(str, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer));
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_BUFFER_FREE(buffer);
Packit Service 31306d
Packit Service 31306d
    return str;
Packit Service 31306d
fail:
Packit Service 31306d
    SSH_BUFFER_FREE(buffer);
Packit Service 31306d
    ssh_string_burn(str);
Packit Service 31306d
    SSH_STRING_FREE(str);
Packit Service 31306d
    ssh_string_burn(e);
Packit Service 31306d
    SSH_STRING_FREE(e);
Packit Service 31306d
    ssh_string_burn(p);
Packit Service 31306d
    SSH_STRING_FREE(p);
Packit Service 31306d
    ssh_string_burn(g);
Packit Service 31306d
    SSH_STRING_FREE(g);
Packit Service 31306d
    ssh_string_burn(q);
Packit Service 31306d
    SSH_STRING_FREE(q);
Packit Service 31306d
    ssh_string_burn(n);
Packit Service 31306d
    SSH_STRING_FREE(n);
Packit Service 31306d
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    char buffer[40] = { 0 };
Packit Service 31306d
    ssh_string sig_blob = NULL;
Packit Service 31306d
    const BIGNUM *pr = NULL, *ps = NULL;
Packit Service 31306d
Packit Service 31306d
    ssh_string r = NULL;
Packit Service 31306d
    int r_len, r_offset_in, r_offset_out;
Packit Service 31306d
Packit Service 31306d
    ssh_string s = NULL;
Packit Service 31306d
    int s_len, s_offset_in, s_offset_out;
Packit Service 31306d
Packit Service 31306d
    const unsigned char *raw_sig_data = NULL;
Packit Service 31306d
    size_t raw_sig_len;
Packit Service 31306d
Packit Service 31306d
    DSA_SIG *dsa_sig;
Packit Service 31306d
Packit Service 31306d
    if (sig == NULL || sig->raw_sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    raw_sig_data = ssh_string_data(sig->raw_sig);
Packit Service 31306d
    if (raw_sig_data == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    raw_sig_len = ssh_string_len(sig->raw_sig);
Packit Service 31306d
Packit Service 31306d
    dsa_sig = d2i_DSA_SIG(NULL, &raw_sig_data, raw_sig_len);
Packit Service 31306d
    if (dsa_sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    DSA_SIG_get0(dsa_sig, &pr, &ps);
Packit Service 31306d
    if (pr == NULL || ps == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    r = ssh_make_bignum_string((BIGNUM *)pr);
Packit Service 31306d
    if (r == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    s = ssh_make_bignum_string((BIGNUM *)ps);
Packit Service 31306d
    if (s == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    r_len = ssh_string_len(r);
Packit Service 31306d
    r_offset_in  = (r_len > 20) ? (r_len - 20) : 0;
Packit Service 31306d
    r_offset_out = (r_len < 20) ? (20 - r_len) : 0;
Packit Service 31306d
Packit Service 31306d
    s_len = ssh_string_len(s);
Packit Service 31306d
    s_offset_in  = (s_len > 20) ? (s_len - 20) : 0;
Packit Service 31306d
    s_offset_out = (s_len < 20) ? (20 - s_len) : 0;
Packit Service 31306d
Packit Service 31306d
    memcpy(buffer + r_offset_out,
Packit Service 31306d
           ((char *)ssh_string_data(r)) + r_offset_in,
Packit Service 31306d
           r_len - r_offset_in);
Packit Service 31306d
    memcpy(buffer + 20 + s_offset_out,
Packit Service 31306d
           ((char *)ssh_string_data(s)) + s_offset_in,
Packit Service 31306d
           s_len - s_offset_in);
Packit Service 31306d
Packit Service 31306d
    DSA_SIG_free(dsa_sig);
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
Packit Service 31306d
    sig_blob = ssh_string_new(40);
Packit Service 31306d
    if (sig_blob == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_string_fill(sig_blob, buffer, 40);
Packit Service 31306d
Packit Service 31306d
    return sig_blob;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    DSA_SIG_free(dsa_sig);
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string r = NULL;
Packit Service 31306d
    ssh_string s = NULL;
Packit Service 31306d
Packit Service 31306d
    ssh_buffer buf = NULL;
Packit Service 31306d
    ssh_string sig_blob = NULL;
Packit Service 31306d
Packit Service 31306d
    const BIGNUM *pr = NULL, *ps = NULL;
Packit Service 31306d
Packit Service 31306d
    const unsigned char *raw_sig_data = NULL;
Packit Service 31306d
    size_t raw_sig_len;
Packit Service 31306d
Packit Service 31306d
    ECDSA_SIG *ecdsa_sig;
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (sig == NULL || sig->raw_sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    raw_sig_data = ssh_string_data(sig->raw_sig);
Packit Service 31306d
    if (raw_sig_data == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    raw_sig_len = ssh_string_len(sig->raw_sig);
Packit Service 31306d
Packit Service 31306d
    ecdsa_sig = d2i_ECDSA_SIG(NULL, &raw_sig_data, raw_sig_len);
Packit Service 31306d
    if (ecdsa_sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ECDSA_SIG_get0(ecdsa_sig, &pr, &ps);
Packit Service 31306d
    if (pr == NULL || ps == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    r = ssh_make_bignum_string((BIGNUM *)pr);
Packit Service 31306d
    if (r == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    s = ssh_make_bignum_string((BIGNUM *)ps);
Packit Service 31306d
    if (s == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    buf = ssh_buffer_new();
Packit Service 31306d
    if (buf == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_add_ssh_string(buf, r);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_add_ssh_string(buf, s);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig_blob = ssh_string_new(ssh_buffer_get_len(buf));
Packit Service 31306d
    if (sig_blob == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf));
Packit Service 31306d
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
    ECDSA_SIG_free(ecdsa_sig);
Packit Service 31306d
    SSH_BUFFER_FREE(buf);
Packit Service 31306d
Packit Service 31306d
    return sig_blob;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
    ECDSA_SIG_free(ecdsa_sig);
Packit Service 31306d
    SSH_BUFFER_FREE(buf);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
ssh_string pki_signature_to_blob(const ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string sig_blob = NULL;
Packit Service 31306d
Packit Service 31306d
    switch(sig->type) {
Packit Service 31306d
        case SSH_KEYTYPE_DSS:
Packit Service 31306d
            sig_blob = pki_dsa_signature_to_blob(sig);
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA1:
Packit Service 31306d
            sig_blob = ssh_string_copy(sig->raw_sig);
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            sig_blob = pki_ed25519_signature_to_blob(sig);
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
            sig_blob = pki_ecdsa_signature_to_blob(sig);
Packit Service 31306d
            break;
Packit Service 31306d
#endif
Packit Service 31306d
        default:
Packit Service 31306d
        case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", sig->type_c);
Packit Service 31306d
            return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return sig_blob;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int pki_signature_from_rsa_blob(const ssh_key pubkey,
Packit Service 31306d
                                       const ssh_string sig_blob,
Packit Service 31306d
                                       ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    uint32_t pad_len = 0;
Packit Service 31306d
    char *blob_orig = NULL;
Packit Service 31306d
    char *blob_padded_data = NULL;
Packit Service 31306d
    ssh_string sig_blob_padded = NULL;
Packit Service 31306d
Packit Service 31306d
    size_t rsalen = 0;
Packit Service 31306d
    size_t len = ssh_string_len(sig_blob);
Packit Service 31306d
Packit Service 31306d
    if (pubkey->rsa == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL");
Packit Service 31306d
        goto errout;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rsalen = RSA_size(pubkey->rsa);
Packit Service 31306d
    if (len > rsalen) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                "Signature is too big: %lu > %lu",
Packit Service 31306d
                (unsigned long)len,
Packit Service 31306d
                (unsigned long)rsalen);
Packit Service 31306d
        goto errout;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef DEBUG_CRYPTO
Packit Service 31306d
    SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len);
Packit Service 31306d
    ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len);
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    if (len == rsalen) {
Packit Service 31306d
        sig->raw_sig = ssh_string_copy(sig_blob);
Packit Service 31306d
    } else {
Packit Service 31306d
        /* pad the blob to the expected rsalen size */
Packit Service 31306d
        SSH_LOG(SSH_LOG_DEBUG,
Packit Service 31306d
                "RSA signature len %lu < %lu",
Packit Service 31306d
                (unsigned long)len,
Packit Service 31306d
                (unsigned long)rsalen);
Packit Service 31306d
Packit Service 31306d
        pad_len = rsalen - len;
Packit Service 31306d
Packit Service 31306d
        sig_blob_padded = ssh_string_new(rsalen);
Packit Service 31306d
        if (sig_blob_padded == NULL) {
Packit Service 31306d
            goto errout;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
Packit Service 31306d
        blob_orig = (char *) ssh_string_data(sig_blob);
Packit Service 31306d
Packit Service 31306d
        if (blob_padded_data == NULL || blob_orig == NULL) {
Packit Service 31306d
            goto errout;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        /* front-pad the buffer with zeroes */
Packit Service 31306d
        explicit_bzero(blob_padded_data, pad_len);
Packit Service 31306d
        /* fill the rest with the actual signature blob */
Packit Service 31306d
        memcpy(blob_padded_data + pad_len, blob_orig, len);
Packit Service 31306d
Packit Service 31306d
        sig->raw_sig = sig_blob_padded;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
errout:
Packit Service 31306d
    SSH_STRING_FREE(sig_blob_padded);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey),
Packit Service 31306d
                                       const ssh_string sig_blob,
Packit Service 31306d
                                       ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    DSA_SIG *dsa_sig = NULL;
Packit Service 31306d
    BIGNUM *pr = NULL, *ps = NULL;
Packit Service 31306d
Packit Service 31306d
    ssh_string r;
Packit Service 31306d
    ssh_string s;
Packit Service 31306d
Packit Service 31306d
    size_t len;
Packit Service 31306d
Packit Service 31306d
    int raw_sig_len = 0;
Packit Service 31306d
    unsigned char *raw_sig_data = NULL;
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    len = ssh_string_len(sig_blob);
Packit Service 31306d
Packit Service 31306d
    /* 40 is the dual signature blob len. */
Packit Service 31306d
    if (len != 40) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                "Signature has wrong size: %lu",
Packit Service 31306d
                (unsigned long)len);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef DEBUG_CRYPTO
Packit Service 31306d
    ssh_log_hexdump("r", ssh_string_data(sig_blob), 20);
Packit Service 31306d
    ssh_log_hexdump("s", (unsigned char *)ssh_string_data(sig_blob) + 20, 20);
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    r = ssh_string_new(20);
Packit Service 31306d
    if (r == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    ssh_string_fill(r, ssh_string_data(sig_blob), 20);
Packit Service 31306d
Packit Service 31306d
    pr = ssh_make_string_bn(r);
Packit Service 31306d
    ssh_string_burn(r);
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    if (pr == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    s = ssh_string_new(20);
Packit Service 31306d
    if (s == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
Packit Service 31306d
Packit Service 31306d
    ps = ssh_make_string_bn(s);
Packit Service 31306d
    ssh_string_burn(s);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
    if (ps == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    dsa_sig = DSA_SIG_new();
Packit Service 31306d
    if (dsa_sig == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of pr and ps is transferred to DSA signature
Packit Service 31306d
     * object */
Packit Service 31306d
    rc = DSA_SIG_set0(dsa_sig, pr, ps);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    ps = NULL;
Packit Service 31306d
    pr = NULL;
Packit Service 31306d
Packit Service 31306d
    raw_sig_len = i2d_DSA_SIG(dsa_sig, &raw_sig_data);
Packit Service 31306d
    if (raw_sig_len < 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig->raw_sig = ssh_string_new(raw_sig_len);
Packit Service 31306d
    if (sig->raw_sig == NULL) {
Packit Service 31306d
        explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
    SAFE_FREE(raw_sig_data);
Packit Service 31306d
    DSA_SIG_free(dsa_sig);
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    bignum_safe_free(ps);
Packit Service 31306d
    bignum_safe_free(pr);
Packit Service 31306d
    SAFE_FREE(raw_sig_data);
Packit Service 31306d
    DSA_SIG_free(dsa_sig);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey),
Packit Service 31306d
                                         const ssh_string sig_blob,
Packit Service 31306d
                                         ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    ECDSA_SIG *ecdsa_sig = NULL;
Packit Service 31306d
    BIGNUM *pr = NULL, *ps = NULL;
Packit Service 31306d
Packit Service 31306d
    ssh_string r;
Packit Service 31306d
    ssh_string s;
Packit Service 31306d
Packit Service 31306d
    ssh_buffer buf = NULL;
Packit Service 31306d
    uint32_t rlen;
Packit Service 31306d
Packit Service 31306d
    unsigned char *raw_sig_data = NULL;
Packit Service 31306d
    size_t raw_sig_len = 0;
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    /* build ecdsa signature */
Packit Service 31306d
    buf = ssh_buffer_new();
Packit Service 31306d
    if (buf == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_add_data(buf,
Packit Service 31306d
                             ssh_string_data(sig_blob),
Packit Service 31306d
                             ssh_string_len(sig_blob));
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    r = ssh_buffer_get_ssh_string(buf);
Packit Service 31306d
    if (r == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef DEBUG_CRYPTO
Packit Service 31306d
    ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r));
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    pr = ssh_make_string_bn(r);
Packit Service 31306d
    ssh_string_burn(r);
Packit Service 31306d
    SSH_STRING_FREE(r);
Packit Service 31306d
    if (pr == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    s = ssh_buffer_get_ssh_string(buf);
Packit Service 31306d
    rlen = ssh_buffer_get_len(buf);
Packit Service 31306d
    SSH_BUFFER_FREE(buf);
Packit Service 31306d
    if (s == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (rlen != 0) {
Packit Service 31306d
        ssh_string_burn(s);
Packit Service 31306d
        SSH_STRING_FREE(s);
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                "Signature has remaining bytes in inner "
Packit Service 31306d
                "sigblob: %lu",
Packit Service 31306d
                (unsigned long)rlen);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef DEBUG_CRYPTO
Packit Service 31306d
    ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s));
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    ps = ssh_make_string_bn(s);
Packit Service 31306d
    ssh_string_burn(s);
Packit Service 31306d
    SSH_STRING_FREE(s);
Packit Service 31306d
    if (ps == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ecdsa_sig = ECDSA_SIG_new();
Packit Service 31306d
    if (ecdsa_sig == NULL) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Memory management of pr and ps is transferred to
Packit Service 31306d
     * ECDSA signature object */
Packit Service 31306d
    rc = ECDSA_SIG_set0(ecdsa_sig, pr, ps);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    pr = NULL;
Packit Service 31306d
    ps = NULL;
Packit Service 31306d
Packit Service 31306d
    rc = i2d_ECDSA_SIG(ecdsa_sig, &raw_sig_data);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    raw_sig_len = rc;
Packit Service 31306d
Packit Service 31306d
    sig->raw_sig = ssh_string_new(raw_sig_len);
Packit Service 31306d
    if (sig->raw_sig == NULL) {
Packit Service 31306d
        explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
    SAFE_FREE(raw_sig_data);
Packit Service 31306d
    ECDSA_SIG_free(ecdsa_sig);
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    SSH_BUFFER_FREE(buf);
Packit Service 31306d
    bignum_safe_free(ps);
Packit Service 31306d
    bignum_safe_free(pr);
Packit Service 31306d
    SAFE_FREE(raw_sig_data);
Packit Service 31306d
    if (ecdsa_sig != NULL) {
Packit Service 31306d
        ECDSA_SIG_free(ecdsa_sig);
Packit Service 31306d
    }
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
Packit Service 31306d
                                      const ssh_string sig_blob,
Packit Service 31306d
                                      enum ssh_keytypes_e type,
Packit Service 31306d
                                      enum ssh_digest_e hash_type)
Packit Service 31306d
{
Packit Service 31306d
    ssh_signature sig;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (ssh_key_type_plain(pubkey->type) != type) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN,
Packit Service 31306d
                "Incompatible public key provided (%d) expecting (%d)",
Packit Service 31306d
                type,
Packit Service 31306d
                pubkey->type);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig = ssh_signature_new();
Packit Service 31306d
    if (sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig->type = type;
Packit Service 31306d
    sig->type_c = ssh_key_signature_to_char(type, hash_type);
Packit Service 31306d
    sig->hash_type = hash_type;
Packit Service 31306d
Packit Service 31306d
    switch(type) {
Packit Service 31306d
        case SSH_KEYTYPE_DSS:
Packit Service 31306d
            rc = pki_signature_from_dsa_blob(pubkey, sig_blob, sig);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA1:
Packit Service 31306d
            rc = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            rc = pki_signature_from_ed25519_blob(sig, sig_blob);
Packit Service 31306d
            if (rc != SSH_OK){
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P256_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384_CERT01:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521_CERT01:
Packit Service 31306d
#ifdef HAVE_OPENSSL_ECC
Packit Service 31306d
            rc = pki_signature_from_ecdsa_blob(pubkey, sig_blob, sig);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
#endif
Packit Service 31306d
        default:
Packit Service 31306d
        case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Unknown signature type");
Packit Service 31306d
            goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return sig;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    ssh_signature_free(sig);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
Packit Service 31306d
{
Packit Service 31306d
    const EVP_MD *md = NULL;
Packit Service 31306d
Packit Service 31306d
    switch (hash_type) {
Packit Service 31306d
    case SSH_DIGEST_SHA256:
Packit Service 31306d
        md = EVP_sha256();
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA384:
Packit Service 31306d
        md = EVP_sha384();
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA512:
Packit Service 31306d
        md = EVP_sha512();
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA1:
Packit Service 31306d
        md = EVP_sha1();
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_AUTO:
Packit Service 31306d
        md = NULL;
Packit Service 31306d
        break;
Packit Service 31306d
    default:
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
Packit Service 31306d
                hash_type);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return md;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static EVP_PKEY *pki_key_to_pkey(ssh_key key)
Packit Service 31306d
{
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
Packit Service 31306d
    switch(key->type) {
Packit Service 31306d
    case SSH_KEYTYPE_DSS:
Packit Service 31306d
    case SSH_KEYTYPE_DSS_CERT01:
Packit Service 31306d
        if (key->dsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa");
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
        pkey = EVP_PKEY_new();
Packit Service 31306d
        if (pkey == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "Out of memory");
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        EVP_PKEY_set1_DSA(pkey, key->dsa);
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_KEYTYPE_RSA:
Packit Service 31306d
    case SSH_KEYTYPE_RSA1:
Packit Service 31306d
    case SSH_KEYTYPE_RSA_CERT01:
Packit Service 31306d
        if (key->rsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa");
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
        pkey = EVP_PKEY_new();
Packit Service 31306d
        if (pkey == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "Out of memory");
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        EVP_PKEY_set1_RSA(pkey, key->rsa);
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P256:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P256_CERT01:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P384_CERT01:
Packit Service 31306d
    case SSH_KEYTYPE_ECDSA_P521_CERT01:
Packit Service 31306d
# if defined(HAVE_OPENSSL_ECC)
Packit Service 31306d
        if (key->ecdsa == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa");
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
        pkey = EVP_PKEY_new();
Packit Service 31306d
        if (pkey == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "Out of memory");
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
Packit Service 31306d
        break;
Packit Service 31306d
# endif
Packit Service 31306d
    case SSH_KEYTYPE_ED25519:
Packit Service 31306d
    case SSH_KEYTYPE_ED25519_CERT01:
Packit Service 31306d
# if defined(HAVE_OPENSSL_ED25519)
Packit Service 31306d
        if (ssh_key_is_private(key)) {
Packit Service 31306d
            if (key->ed25519_privkey == NULL) {
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_privkey");
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            /* In OpenSSL, the input is the private key seed only, which means
Packit Service 31306d
             * the first half of the SSH private key (the second half is the
Packit Service 31306d
             * public key). Both keys have the same length (32 bytes) */
Packit Service 31306d
            pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
Packit Service 31306d
                    (const uint8_t *)key->ed25519_privkey,
Packit Service 31306d
                    ED25519_KEY_LEN);
Packit Service 31306d
        } else {
Packit Service 31306d
            if (key->ed25519_pubkey == NULL) {
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_pubkey");
Packit Service 31306d
                goto error;
Packit Service 31306d
            }
Packit Service 31306d
            pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
Packit Service 31306d
                    (const uint8_t *)key->ed25519_pubkey,
Packit Service 31306d
                    ED25519_KEY_LEN);
Packit Service 31306d
        }
Packit Service 31306d
        if (pkey == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                    "Failed to create ed25519 EVP_PKEY: %s",
Packit Service 31306d
                    ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
        break;
Packit Service 31306d
#endif
Packit Service 31306d
    case SSH_KEYTYPE_UNKNOWN:
Packit Service 31306d
    default:
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Unknown private key algorithm for type: %d",
Packit Service 31306d
                key->type);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return pkey;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
    return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Sign the given input data. The digest of to be signed is calculated
Packit Service 31306d
 * internally as necessary.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]   privkey     The private key to be used for signing.
Packit Service 31306d
 * @param[in]   hash_type   The digest algorithm to be used.
Packit Service 31306d
 * @param[in]   input       The data to be signed.
Packit Service 31306d
 * @param[in]   input_len   The length of the data to be signed.
Packit Service 31306d
 *
Packit Service 31306d
 * @return  a newly allocated ssh_signature or NULL on error.
Packit Service 31306d
 */
Packit Service 31306d
ssh_signature pki_sign_data(const ssh_key privkey,
Packit Service 31306d
                            enum ssh_digest_e hash_type,
Packit Service 31306d
                            const unsigned char *input,
Packit Service 31306d
                            size_t input_len)
Packit Service 31306d
{
Packit Service 31306d
    const EVP_MD *md = NULL;
Packit Service 31306d
    EVP_MD_CTX *ctx = NULL;
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
Packit Service 31306d
    unsigned char *raw_sig_data = NULL;
Packit Service 31306d
    size_t raw_sig_len;
Packit Service 31306d
Packit Service 31306d
    ssh_signature sig = NULL;
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (privkey == NULL || !ssh_key_is_private(privkey) || input == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
Packit Service 31306d
                               "pki_sign_data()");
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Check if public key and hash type are compatible */
Packit Service 31306d
    rc = pki_key_check_hash_compatible(privkey, hash_type);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifndef HAVE_OPENSSL_ED25519
Packit Service 31306d
    if (privkey->type == SSH_KEYTYPE_ED25519 ||
Packit Service 31306d
        privkey->type == SSH_KEYTYPE_ED25519_CERT01)
Packit Service 31306d
    {
Packit Service 31306d
        return pki_do_sign_hash(privkey, input, input_len, hash_type);
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    /* Set hash algorithm to be used */
Packit Service 31306d
    md = pki_digest_to_md(hash_type);
Packit Service 31306d
    if (md == NULL) {
Packit Service 31306d
        if (hash_type != SSH_DIGEST_AUTO) {
Packit Service 31306d
            return NULL;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Setup private key EVP_PKEY */
Packit Service 31306d
    pkey = pki_key_to_pkey(privkey);
Packit Service 31306d
    if (pkey == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Allocate buffer for signature */
Packit Service 31306d
    raw_sig_len = (size_t)EVP_PKEY_size(pkey);
Packit Service 31306d
    raw_sig_data = (unsigned char *)malloc(raw_sig_len);
Packit Service 31306d
    if (raw_sig_data == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Out of memory");
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Create the context */
Packit Service 31306d
    ctx = EVP_MD_CTX_create();
Packit Service 31306d
    if (ctx == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Out of memory");
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Sign the data */
Packit Service 31306d
    rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
Packit Service 31306d
    if (rc != 1){
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestSignInit() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_EVP_DIGESTSIGN
Packit Service 31306d
    rc = EVP_DigestSign(ctx, raw_sig_data, &raw_sig_len, input, input_len);
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestSign() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
#else
Packit Service 31306d
    rc = EVP_DigestSignUpdate(ctx, input, input_len);
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestSignUpdate() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = EVP_DigestSignFinal(ctx, raw_sig_data, &raw_sig_len);
Packit Service 31306d
    if (rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestSignFinal() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#ifdef DEBUG_CRYPTO
Packit Service 31306d
        ssh_log_hexdump("Generated signature", raw_sig_data, raw_sig_len);
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    /* Allocate and fill output signature */
Packit Service 31306d
    sig = ssh_signature_new();
Packit Service 31306d
    if (sig == NULL) {
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig->raw_sig = ssh_string_new(raw_sig_len);
Packit Service 31306d
    if (sig->raw_sig == NULL) {
Packit Service 31306d
        ssh_signature_free(sig);
Packit Service 31306d
        sig = NULL;
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        ssh_signature_free(sig);
Packit Service 31306d
        sig = NULL;
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig->type = privkey->type;
Packit Service 31306d
    sig->hash_type = hash_type;
Packit Service 31306d
    sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
Packit Service 31306d
Packit Service 31306d
out:
Packit Service 31306d
    if (ctx != NULL) {
Packit Service 31306d
        EVP_MD_CTX_free(ctx);
Packit Service 31306d
    }
Packit Service 31306d
    if (raw_sig_data != NULL) {
Packit Service 31306d
        explicit_bzero(raw_sig_data, raw_sig_len);
Packit Service 31306d
    }
Packit Service 31306d
    SAFE_FREE(raw_sig_data);
Packit Service 31306d
    if (pkey != NULL) {
Packit Service 31306d
        EVP_PKEY_free(pkey);
Packit Service 31306d
    }
Packit Service 31306d
    return sig;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Verify the signature of a given input. The digest of the input is
Packit Service 31306d
 * calculated internally as necessary.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]   signature   The signature to be verified.
Packit Service 31306d
 * @param[in]   pubkey      The public key used to verify the signature.
Packit Service 31306d
 * @param[in]   input       The signed data.
Packit Service 31306d
 * @param[in]   input_len   The length of the signed data.
Packit Service 31306d
 *
Packit Service 31306d
 * @return  SSH_OK if the signature is valid; SSH_ERROR otherwise.
Packit Service 31306d
 */
Packit Service 31306d
int pki_verify_data_signature(ssh_signature signature,
Packit Service 31306d
                              const ssh_key pubkey,
Packit Service 31306d
                              const unsigned char *input,
Packit Service 31306d
                              size_t input_len)
Packit Service 31306d
{
Packit Service 31306d
    const EVP_MD *md = NULL;
Packit Service 31306d
    EVP_MD_CTX *ctx = NULL;
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
Packit Service 31306d
    unsigned char *raw_sig_data = NULL;
Packit Service 31306d
    unsigned int raw_sig_len;
Packit Service 31306d
Packit Service 31306d
    int rc = SSH_ERROR;
Packit Service 31306d
    int evp_rc;
Packit Service 31306d
Packit Service 31306d
    if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
Packit Service 31306d
        signature == NULL || (signature->raw_sig == NULL
Packit Service 31306d
#ifndef HAVE_OPENSSL_ED25519
Packit Service 31306d
        && signature->ed25519_sig == NULL
Packit Service 31306d
#endif
Packit Service 31306d
        ))
Packit Service 31306d
    {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to "
Packit Service 31306d
                               "pki_verify_data_signature()");
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Check if public key and hash type are compatible */
Packit Service 31306d
    rc = pki_key_check_hash_compatible(pubkey, signature->hash_type);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifndef HAVE_OPENSSL_ED25519
Packit Service 31306d
    if (pubkey->type == SSH_KEYTYPE_ED25519 ||
Packit Service 31306d
        pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
Packit Service 31306d
    {
Packit Service 31306d
        return pki_ed25519_verify(pubkey, signature, input, input_len);
Packit Service 31306d
    }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    /* Get the signature to be verified */
Packit Service 31306d
    raw_sig_data = ssh_string_data(signature->raw_sig);
Packit Service 31306d
    raw_sig_len = ssh_string_len(signature->raw_sig);
Packit Service 31306d
    if (raw_sig_data == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Set hash algorithm to be used */
Packit Service 31306d
    md = pki_digest_to_md(signature->hash_type);
Packit Service 31306d
    if (md == NULL) {
Packit Service 31306d
        if (signature->hash_type != SSH_DIGEST_AUTO) {
Packit Service 31306d
            return SSH_ERROR;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Setup public key EVP_PKEY */
Packit Service 31306d
    pkey = pki_key_to_pkey(pubkey);
Packit Service 31306d
    if (pkey == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Create the context */
Packit Service 31306d
    ctx = EVP_MD_CTX_create();
Packit Service 31306d
    if (ctx == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to create EVP_MD_CTX: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Verify the signature */
Packit Service 31306d
    evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey);
Packit Service 31306d
    if (evp_rc != 1){
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestVerifyInit() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY
Packit Service 31306d
    evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len);
Packit Service 31306d
#else
Packit Service 31306d
    evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len);
Packit Service 31306d
    if (evp_rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "EVP_DigestVerifyUpdate() failed: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto out;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len);
Packit Service 31306d
#endif
Packit Service 31306d
    if (evp_rc == 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Signature valid");
Packit Service 31306d
        rc = SSH_OK;
Packit Service 31306d
    } else {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Signature invalid: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        rc = SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
out:
Packit Service 31306d
    if (ctx != NULL) {
Packit Service 31306d
        EVP_MD_CTX_free(ctx);
Packit Service 31306d
    }
Packit Service 31306d
    if (pkey != NULL) {
Packit Service 31306d
        EVP_PKEY_free(pkey);
Packit Service 31306d
    }
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_OPENSSL_ED25519
Packit Service 31306d
int pki_key_generate_ed25519(ssh_key key)
Packit Service 31306d
{
Packit Service 31306d
    int evp_rc;
Packit Service 31306d
    EVP_PKEY_CTX *pctx = NULL;
Packit Service 31306d
    EVP_PKEY *pkey = NULL;
Packit Service 31306d
    size_t privkey_len = ED25519_KEY_LEN;
Packit Service 31306d
    size_t pubkey_len = ED25519_KEY_LEN;
Packit Service 31306d
Packit Service 31306d
    if (key == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
Packit Service 31306d
    if (pctx == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to create ed25519 EVP_PKEY_CTX: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    evp_rc = EVP_PKEY_keygen_init(pctx);
Packit Service 31306d
    if (evp_rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to initialize ed25519 key generation: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    evp_rc = EVP_PKEY_keygen(pctx, &pkey);
Packit Service 31306d
    if (evp_rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to generate ed25519 key: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    key->ed25519_privkey = malloc(ED25519_KEY_LEN);
Packit Service 31306d
    if (key->ed25519_privkey == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to allocate memory for ed25519 private key");
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
Packit Service 31306d
    if (key->ed25519_pubkey == NULL) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to allocate memory for ed25519 public key");
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)key->ed25519_privkey,
Packit Service 31306d
                                          &privkey_len);
Packit Service 31306d
    if (evp_rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to get ed25519 raw private key: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    evp_rc = EVP_PKEY_get_raw_public_key(pkey, (uint8_t *)key->ed25519_pubkey,
Packit Service 31306d
                                         &pubkey_len);
Packit Service 31306d
    if (evp_rc != 1) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE,
Packit Service 31306d
                "Failed to get ed25519 raw public key: %s",
Packit Service 31306d
                ERR_error_string(ERR_get_error(), NULL));
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    EVP_PKEY_CTX_free(pctx);
Packit Service 31306d
    EVP_PKEY_free(pkey);
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
    if (pctx != NULL) {
Packit Service 31306d
        EVP_PKEY_CTX_free(pctx);
Packit Service 31306d
    }
Packit Service 31306d
    if (pkey != NULL) {
Packit Service 31306d
        EVP_PKEY_free(pkey);
Packit Service 31306d
    }
Packit Service 31306d
    SAFE_FREE(key->ed25519_privkey);
Packit Service 31306d
    SAFE_FREE(key->ed25519_pubkey);
Packit Service 31306d
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
#else
Packit Service 31306d
ssh_signature pki_do_sign_hash(const ssh_key privkey,
Packit Service 31306d
                               const unsigned char *hash,
Packit Service 31306d
                               size_t hlen,
Packit Service 31306d
                               enum ssh_digest_e hash_type)
Packit Service 31306d
{
Packit Service 31306d
    ssh_signature sig = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    sig = ssh_signature_new();
Packit Service 31306d
    if (sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig->type = privkey->type;
Packit Service 31306d
    sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
Packit Service 31306d
    sig->hash_type = hash_type;
Packit Service 31306d
Packit Service 31306d
    switch(privkey->type) {
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            rc = pki_ed25519_sign(privkey, sig, hash, hlen);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            ssh_signature_free(sig);
Packit Service 31306d
            return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return sig;
Packit Service 31306d
}
Packit Service 31306d
#endif /* HAVE_OPENSSL_ED25519 */
Packit Service 31306d
Packit Service 31306d
#endif /* _PKI_CRYPTO_H */