Blame src/pki_mbedcrypto.c

Packit Service 31306d
/*
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2017 Sartura d.o.o.
Packit Service 31306d
 *
Packit Service 31306d
 * Author: Juraj Vijtiuk <juraj.vijtiuk@sartura.hr>
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
#include "config.h"
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_LIBMBEDCRYPTO
Packit Service 31306d
#include <mbedtls/pk.h>
Packit Service 31306d
#include <mbedtls/error.h>
Packit Service 31306d
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
#include "libssh/pki.h"
Packit Service 31306d
#include "libssh/pki_priv.h"
Packit Service 31306d
#include "libssh/buffer.h"
Packit Service 31306d
#include "libssh/bignum.h"
Packit Service 31306d
#include "libssh/misc.h"
Packit Service 31306d
Packit Service 31306d
#define MAX_PASSPHRASE_SIZE 1024
Packit Service 31306d
#define MAX_KEY_SIZE 32
Packit Service 31306d
Packit Service 31306d
ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase,
Packit Service 31306d
        ssh_auth_callback auth_fn, void *auth_data)
Packit Service 31306d
{
Packit Service 31306d
    (void) key;
Packit Service 31306d
    (void) passphrase;
Packit Service 31306d
    (void) auth_fn;
Packit Service 31306d
    (void) auth_data; return NULL;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int pki_key_ecdsa_to_nid(mbedtls_ecdsa_context *ecdsa)
Packit Service 31306d
{
Packit Service 31306d
    mbedtls_ecp_group_id id;
Packit Service 31306d
Packit Service 31306d
    id = ecdsa->grp.id;
Packit Service 31306d
    if (id == MBEDTLS_ECP_DP_SECP256R1) {
Packit Service 31306d
        return NID_mbedtls_nistp256;
Packit Service 31306d
    } else if (id == MBEDTLS_ECP_DP_SECP384R1) {
Packit Service 31306d
        return NID_mbedtls_nistp384;
Packit Service 31306d
    } else if (id == MBEDTLS_ECP_DP_SECP521R1) {
Packit Service 31306d
        return NID_mbedtls_nistp521;
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(mbedtls_ecdsa_context *ecdsa)
Packit Service 31306d
{
Packit Service 31306d
    int nid;
Packit Service 31306d
Packit Service 31306d
    nid = pki_key_ecdsa_to_nid(ecdsa);
Packit Service 31306d
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_mbedtls_nistp256:
Packit Service 31306d
            return SSH_KEYTYPE_ECDSA_P256;
Packit Service 31306d
        case NID_mbedtls_nistp384:
Packit Service 31306d
            return SSH_KEYTYPE_ECDSA_P384;
Packit Service 31306d
        case NID_mbedtls_nistp521:
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
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
Packit Service 31306d
        ssh_auth_callback auth_fn, void *auth_data)
Packit Service 31306d
{
Packit Service 31306d
    ssh_key key = NULL;
Packit Service 31306d
    mbedtls_pk_context *rsa = NULL;
Packit Service 31306d
    mbedtls_pk_context *ecdsa = NULL;
Packit Service 31306d
    ed25519_privkey *ed25519 = NULL;
Packit Service 31306d
    enum ssh_keytypes_e type;
Packit Service 31306d
    int valid;
Packit Service 31306d
    /* mbedtls pk_parse_key expects strlen to count the 0 byte */
Packit Service 31306d
    size_t b64len = strlen(b64_key) + 1;
Packit Service 31306d
    unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0};
Packit Service 31306d
Packit Service 31306d
    type = pki_privatekey_type_from_string(b64_key);
Packit Service 31306d
    if (type == SSH_KEYTYPE_UNKNOWN) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (type) {
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
            rsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
            if (rsa == NULL) {
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            mbedtls_pk_init(rsa);
Packit Service 31306d
Packit Service 31306d
            if (passphrase == NULL) {
Packit Service 31306d
                if (auth_fn) {
Packit Service 31306d
                    valid = auth_fn("Passphrase for private key:", (char *) tmp,
Packit Service 31306d
                            MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
Packit Service 31306d
                    if (valid < 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
                    /* TODO fix signedness and strlen */
Packit Service 31306d
                    valid = mbedtls_pk_parse_key(rsa,
Packit Service 31306d
                            (const unsigned char *) b64_key,
Packit Service 31306d
                            b64len, tmp,
Packit Service 31306d
                            strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
Packit Service 31306d
                } else {
Packit Service 31306d
                    valid = mbedtls_pk_parse_key(rsa,
Packit Service 31306d
                            (const unsigned char *) b64_key,
Packit Service 31306d
                            b64len, NULL,
Packit Service 31306d
                            0);
Packit Service 31306d
                }
Packit Service 31306d
            } else {
Packit Service 31306d
                valid = mbedtls_pk_parse_key(rsa,
Packit Service 31306d
                        (const unsigned char *) b64_key, b64len,
Packit Service 31306d
                        (const unsigned char *) passphrase,
Packit Service 31306d
                        strnlen(passphrase, MAX_PASSPHRASE_SIZE));
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (valid != 0) {
Packit Service 31306d
                char error_buf[100];
Packit Service 31306d
                mbedtls_strerror(valid, error_buf, 100);
Packit Service 31306d
                SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
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
            ecdsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
            if (ecdsa == NULL) {
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            mbedtls_pk_init(ecdsa);
Packit Service 31306d
Packit Service 31306d
            if (passphrase == NULL) {
Packit Service 31306d
                if (auth_fn) {
Packit Service 31306d
                    valid = auth_fn("Passphrase for private key:", (char *) tmp,
Packit Service 31306d
                            MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
Packit Service 31306d
                    if (valid < 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
                    valid = mbedtls_pk_parse_key(ecdsa,
Packit Service 31306d
                            (const unsigned char *) b64_key,
Packit Service 31306d
                            b64len, tmp,
Packit Service 31306d
                            strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
Packit Service 31306d
                } else {
Packit Service 31306d
                    valid = mbedtls_pk_parse_key(ecdsa,
Packit Service 31306d
                            (const unsigned char *) b64_key,
Packit Service 31306d
                            b64len, NULL,
Packit Service 31306d
                            0);
Packit Service 31306d
                }
Packit Service 31306d
            } else {
Packit Service 31306d
                valid = mbedtls_pk_parse_key(ecdsa,
Packit Service 31306d
                        (const unsigned char *) b64_key, b64len,
Packit Service 31306d
                        (const unsigned char *) passphrase,
Packit Service 31306d
                        strnlen(passphrase, MAX_PASSPHRASE_SIZE));
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (valid != 0) {
Packit Service 31306d
                char error_buf[100];
Packit Service 31306d
                mbedtls_strerror(valid, error_buf, 100);
Packit Service 31306d
                SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            /* Cannot open ed25519 keys with libmbedcrypto */
Packit Service 31306d
        default:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
Packit Service 31306d
                    type);
Packit Service 31306d
            return NULL;
Packit Service 31306d
    }
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
    if (ecdsa != NULL) {
Packit Service 31306d
        mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa);
Packit Service 31306d
Packit Service 31306d
        key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
Packit Service 31306d
        if (key->ecdsa == NULL) {
Packit Service 31306d
            goto fail;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        mbedtls_ecdsa_init(key->ecdsa);
Packit Service 31306d
        mbedtls_ecdsa_from_keypair(key->ecdsa, keypair);
Packit Service 31306d
        mbedtls_pk_free(ecdsa);
Packit Service 31306d
        SAFE_FREE(ecdsa);
Packit Service 31306d
Packit Service 31306d
        key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
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(key->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
    } else {
Packit Service 31306d
        key->ecdsa = NULL;
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->rsa = rsa;
Packit Service 31306d
    key->ed25519_privkey = ed25519;
Packit Service 31306d
    rsa = NULL;
Packit Service 31306d
    ecdsa = NULL;
Packit Service 31306d
Packit Service 31306d
    return key;
Packit Service 31306d
fail:
Packit Service 31306d
    ssh_key_free(key);
Packit Service 31306d
    if (rsa != NULL) {
Packit Service 31306d
        mbedtls_pk_free(rsa);
Packit Service 31306d
        SAFE_FREE(rsa);
Packit Service 31306d
    }
Packit Service 31306d
    if (ecdsa != NULL) {
Packit Service 31306d
        mbedtls_pk_free(ecdsa);
Packit Service 31306d
        SAFE_FREE(ecdsa);
Packit Service 31306d
    }
Packit Service 31306d
    return NULL;
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
    mbedtls_rsa_context *rsa = NULL;
Packit Service 31306d
    const mbedtls_pk_info_t *pk_info = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    key->rsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
    if (key->rsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_pk_init(key->rsa);
Packit Service 31306d
    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
Packit Service 31306d
    mbedtls_pk_setup(key->rsa, pk_info);
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rsa = mbedtls_pk_rsa(*key->rsa);
Packit Service 31306d
    rc = mbedtls_rsa_import_raw(rsa,
Packit Service 31306d
                                ssh_string_data(n), ssh_string_len(n),
Packit Service 31306d
                                ssh_string_data(p), ssh_string_len(p),
Packit Service 31306d
                                ssh_string_data(q), ssh_string_len(q),
Packit Service 31306d
                                ssh_string_data(d), ssh_string_len(d),
Packit Service 31306d
                                ssh_string_data(e), ssh_string_len(e));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key");
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_rsa_complete(rsa);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key");
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_rsa_check_privkey(rsa);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key");
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
fail:
Packit Service 31306d
    mbedtls_pk_free(key->rsa);
Packit Service 31306d
    SAFE_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, ssh_string e, ssh_string n)
Packit Service 31306d
{
Packit Service 31306d
    mbedtls_rsa_context *rsa = NULL;
Packit Service 31306d
    const mbedtls_pk_info_t *pk_info = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    key->rsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
    if (key->rsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_pk_init(key->rsa);
Packit Service 31306d
    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
Packit Service 31306d
    mbedtls_pk_setup(key->rsa, pk_info);
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA);
Packit Service 31306d
    if (rc == 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rsa = mbedtls_pk_rsa(*key->rsa);
Packit Service 31306d
    rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
Packit Service 31306d
                                 ssh_string_len(n));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
    rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
Packit Service 31306d
                                 ssh_string_len(e));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
fail:
Packit Service 31306d
    mbedtls_pk_free(key->rsa);
Packit Service 31306d
    SAFE_FREE(key->rsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
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 = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
    const mbedtls_pk_info_t *pk_info = NULL;
Packit Service 31306d
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
Packit Service 31306d
    switch(key->type) {
Packit Service 31306d
        case SSH_KEYTYPE_RSA: {
Packit Service 31306d
            mbedtls_rsa_context *rsa, *new_rsa;
Packit Service 31306d
Packit Service 31306d
            new->rsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
            if (new->rsa == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            mbedtls_pk_init(new->rsa);
Packit Service 31306d
            pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
Packit Service 31306d
            mbedtls_pk_setup(new->rsa, pk_info);
Packit Service 31306d
Packit Service 31306d
            if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) &&
Packit Service 31306d
                        mbedtls_pk_can_do(new->rsa, MBEDTLS_PK_RSA)) {
Packit Service 31306d
                rsa = mbedtls_pk_rsa(*key->rsa);
Packit Service 31306d
                new_rsa = mbedtls_pk_rsa(*new->rsa);
Packit Service 31306d
Packit Service 31306d
                rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N);
Packit Service 31306d
                if (rc != 0) {
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                rc = mbedtls_mpi_copy(&new_rsa->E, &rsa->E);
Packit Service 31306d
                if (rc != 0) {
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
                new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3;
Packit Service 31306d
Packit Service 31306d
                if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->P, &rsa->P);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->Q, &rsa->Q);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->DP, &rsa->DP);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->DQ, &rsa->DQ);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    rc = mbedtls_mpi_copy(&new_rsa->QP, &rsa->QP);
Packit Service 31306d
                    if (rc != 0) {
Packit Service 31306d
                        goto fail;
Packit Service 31306d
                    }
Packit Service 31306d
                }
Packit Service 31306d
            } else {
Packit Service 31306d
                goto fail;
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
            new->ecdsa_nid = key->ecdsa_nid;
Packit Service 31306d
Packit Service 31306d
            new->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
Packit Service 31306d
Packit Service 31306d
            if (new->ecdsa == NULL) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            mbedtls_ecdsa_init(new->ecdsa);
Packit Service 31306d
Packit Service 31306d
            if (demote && ssh_key_is_private(key)) {
Packit Service 31306d
                rc = mbedtls_ecp_copy(&new->ecdsa->Q, &key->ecdsa->Q);
Packit Service 31306d
                if (rc != 0) {
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                rc = mbedtls_ecp_group_copy(&new->ecdsa->grp, &key->ecdsa->grp);
Packit Service 31306d
                if (rc != 0) {
Packit Service 31306d
                    goto fail;
Packit Service 31306d
                }
Packit Service 31306d
            } else {
Packit Service 31306d
                mbedtls_ecdsa_from_keypair(new->ecdsa, key->ecdsa);
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            break;
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
        default:
Packit Service 31306d
            goto fail;
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
{
Packit Service 31306d
    int rc;
Packit Service 31306d
    const mbedtls_pk_info_t *info = NULL;
Packit Service 31306d
Packit Service 31306d
    key->rsa = malloc(sizeof(mbedtls_pk_context));
Packit Service 31306d
    if (key->rsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_pk_init(key->rsa);
Packit Service 31306d
Packit Service 31306d
    info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
Packit Service 31306d
    rc = mbedtls_pk_setup(key->rsa, info);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) {
Packit Service 31306d
        rc = mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key->rsa),
Packit Service 31306d
                                 mbedtls_ctr_drbg_random,
Packit Service 31306d
                                 ssh_get_mbedtls_ctr_drbg_context(),
Packit Service 31306d
                                 parameter,
Packit Service 31306d
                                 65537);
Packit Service 31306d
        if (rc != 0) {
Packit Service 31306d
            mbedtls_pk_free(key->rsa);
Packit Service 31306d
            return SSH_ERROR;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
Packit Service 31306d
{
Packit Service 31306d
    switch (k1->type) {
Packit Service 31306d
        case SSH_KEYTYPE_RSA: {
Packit Service 31306d
            mbedtls_rsa_context *rsa1, *rsa2;
Packit Service 31306d
            if (mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) &&
Packit Service 31306d
                    mbedtls_pk_can_do(k2->rsa, MBEDTLS_PK_RSA)) {
Packit Service 31306d
                if (mbedtls_pk_get_type(k1->rsa) != mbedtls_pk_get_type(k2->rsa) ||
Packit Service 31306d
                        mbedtls_pk_get_bitlen(k1->rsa) !=
Packit Service 31306d
                        mbedtls_pk_get_bitlen(k2->rsa)) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                rsa1 = mbedtls_pk_rsa(*k1->rsa);
Packit Service 31306d
                rsa2 = mbedtls_pk_rsa(*k2->rsa);
Packit Service 31306d
                if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                if (mbedtls_mpi_cmp_mpi(&rsa1->E, &rsa2->E) != 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 (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) {
Packit Service 31306d
                        return 1;
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) {
Packit Service 31306d
                        return 1;
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
            mbedtls_ecp_keypair *ecdsa1 = k1->ecdsa;
Packit Service 31306d
            mbedtls_ecp_keypair *ecdsa2 = k2->ecdsa;
Packit Service 31306d
Packit Service 31306d
            if (ecdsa1->grp.id != ecdsa2->grp.id) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.X, &ecdsa2->Q.X)) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Y, &ecdsa2->Q.Y)) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Z, &ecdsa2->Q.Z)) {
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (what == SSH_KEY_CMP_PRIVATE) {
Packit Service 31306d
                if (mbedtls_mpi_cmp_mpi(&ecdsa1->d, &ecdsa2->d)) {
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            /* ed25519 keys handled globally */
Packit Service 31306d
            return 0;
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 make_ecpoint_string(const mbedtls_ecp_group *g, const
Packit Service 31306d
        mbedtls_ecp_point *p)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string s = NULL;
Packit Service 31306d
    size_t len = 1;
Packit Service 31306d
    int rc;
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
    rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
Packit Service 31306d
                &len, ssh_string_data(s), ssh_string_len(s));
Packit Service 31306d
    if (rc == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
Packit Service 31306d
        SSH_STRING_FREE(s);
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
        rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED,
Packit Service 31306d
                &len, ssh_string_data(s), ssh_string_len(s));
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        SSH_STRING_FREE(s);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
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
static const char* pki_key_ecdsa_nid_to_char(int nid)
Packit Service 31306d
{
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_mbedtls_nistp256:
Packit Service 31306d
            return "nistp256";
Packit Service 31306d
        case NID_mbedtls_nistp384:
Packit Service 31306d
            return "nistp384";
Packit Service 31306d
        case NID_mbedtls_nistp521:
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
ssh_string pki_publickey_to_blob(const ssh_key key)
Packit Service 31306d
{
Packit Service 31306d
    ssh_buffer buffer = NULL;
Packit Service 31306d
    ssh_string type_s = NULL;
Packit Service 31306d
    ssh_string e = NULL;
Packit Service 31306d
    ssh_string n = NULL;
Packit Service 31306d
    ssh_string str = 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
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_RSA: {
Packit Service 31306d
            mbedtls_rsa_context *rsa;
Packit Service 31306d
            if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) == 0) {
Packit Service 31306d
                SSH_BUFFER_FREE(buffer);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rsa = mbedtls_pk_rsa(*key->rsa);
Packit Service 31306d
Packit Service 31306d
            e = ssh_make_bignum_string(&rsa->E);
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(&rsa->N);
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
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_ECDSA_P256:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P384:
Packit Service 31306d
        case SSH_KEYTYPE_ECDSA_P521:
Packit Service 31306d
            type_s =
Packit Service 31306d
                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(&key->ecdsa->grp, &key->ecdsa->Q);
Packit Service 31306d
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
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
            rc = pki_ed25519_public_key_to_blob(buffer, key);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                goto fail;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            goto fail;
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),
Packit Service 31306d
            ssh_buffer_get_len(buffer));
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SSH_BUFFER_FREE(buffer);
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(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
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_RSA:
Packit Service 31306d
            sig_blob = ssh_string_copy(sig->rsa_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
            ssh_string r;
Packit Service 31306d
            ssh_string s;
Packit Service 31306d
            ssh_buffer b;
Packit Service 31306d
            int rc;
Packit Service 31306d
Packit Service 31306d
            b = ssh_buffer_new();
Packit Service 31306d
            if (b == NULL) {
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            r = ssh_make_bignum_string(sig->ecdsa_sig.r);
Packit Service 31306d
            if (r == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_buffer_add_ssh_string(b, r);
Packit Service 31306d
            SSH_STRING_FREE(r);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            s = ssh_make_bignum_string(sig->ecdsa_sig.s);
Packit Service 31306d
            if (s == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_buffer_add_ssh_string(b, s);
Packit Service 31306d
            SSH_STRING_FREE(s);
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            sig_blob = ssh_string_new(ssh_buffer_get_len(b));
Packit Service 31306d
            if (sig_blob == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b));
Packit Service 31306d
            SSH_BUFFER_FREE(b);
Packit Service 31306d
            break;
Packit Service 31306d
        }
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
        default:
Packit Service 31306d
            SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s",
Packit Service 31306d
                    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 ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey, const
Packit Service 31306d
        ssh_string sig_blob, ssh_signature sig)
Packit Service 31306d
{
Packit Service 31306d
    size_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 = mbedtls_pk_get_bitlen(pubkey->rsa) / 8;
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
#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->rsa_sig = ssh_string_copy(sig_blob);
Packit Service 31306d
    } else {
Packit Service 31306d
        SSH_LOG(SSH_LOG_DEBUG, "RSA signature len %lu < %lu",
Packit Service 31306d
                (unsigned long) len,
Packit Service 31306d
                (unsigned long) rsalen);
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
        explicit_bzero(blob_padded_data, pad_len);
Packit Service 31306d
        memcpy(blob_padded_data + pad_len, blob_orig, len);
Packit Service 31306d
Packit Service 31306d
        sig->rsa_sig = sig_blob_padded;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return sig;
Packit Service 31306d
Packit Service 31306d
errout:
Packit Service 31306d
    ssh_signature_free(sig);
Packit Service 31306d
    return NULL;
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 = NULL;
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_RSA:
Packit Service 31306d
            sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
Packit Service 31306d
            if (sig == NULL) {
Packit Service 31306d
                return NULL;
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
            ssh_buffer b;
Packit Service 31306d
            ssh_string r;
Packit Service 31306d
            ssh_string s;
Packit Service 31306d
            size_t rlen;
Packit Service 31306d
Packit Service 31306d
            b = ssh_buffer_new();
Packit Service 31306d
            if (b == NULL) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = ssh_buffer_add_data(b, ssh_string_data(sig_blob),
Packit Service 31306d
                    ssh_string_len(sig_blob));
Packit Service 31306d
Packit Service 31306d
            if (rc < 0) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            r = ssh_buffer_get_ssh_string(b);
Packit Service 31306d
            if (r == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
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
            sig->ecdsa_sig.r = ssh_make_string_bn(r);
Packit Service 31306d
            ssh_string_burn(r);
Packit Service 31306d
            SSH_STRING_FREE(r);
Packit Service 31306d
            if (sig->ecdsa_sig.r == NULL) {
Packit Service 31306d
                SSH_BUFFER_FREE(b);
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            s = ssh_buffer_get_ssh_string(b);
Packit Service 31306d
            rlen = ssh_buffer_get_len(b);
Packit Service 31306d
            SSH_BUFFER_FREE(b);
Packit Service 31306d
            if (s == NULL) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
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
            sig->ecdsa_sig.s = ssh_make_string_bn(s);
Packit Service 31306d
            ssh_string_burn(s);
Packit Service 31306d
            SSH_STRING_FREE(s);
Packit Service 31306d
            if (sig->ecdsa_sig.s == NULL) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (rlen != 0) {
Packit Service 31306d
                SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner "
Packit Service 31306d
                        "sigblob: %lu",
Packit Service 31306d
                        (unsigned long)rlen);
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            break;
Packit Service 31306d
        }
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_ERROR) {
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_LOG(SSH_LOG_WARN, "Unknown signature type");
Packit Service 31306d
            return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return sig;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static ssh_string rsa_do_sign_hash(const unsigned char *digest,
Packit Service 31306d
                                   int dlen,
Packit Service 31306d
                                   mbedtls_pk_context *privkey,
Packit Service 31306d
                                   enum ssh_digest_e hash_type)
Packit Service 31306d
{
Packit Service 31306d
    ssh_string sig_blob = NULL;
Packit Service 31306d
    mbedtls_md_type_t md = 0;
Packit Service 31306d
    unsigned char *sig = NULL;
Packit Service 31306d
    size_t slen;
Packit Service 31306d
    int ok;
Packit Service 31306d
Packit Service 31306d
    switch (hash_type) {
Packit Service 31306d
    case SSH_DIGEST_SHA1:
Packit Service 31306d
        md = MBEDTLS_MD_SHA1;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA256:
Packit Service 31306d
        md = MBEDTLS_MD_SHA256;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA512:
Packit Service 31306d
        md = MBEDTLS_MD_SHA512;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_AUTO:
Packit Service 31306d
    default:
Packit Service 31306d
        SSH_LOG(SSH_LOG_WARN, "Incompatible key algorithm");
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8);
Packit Service 31306d
    if (sig == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ok = mbedtls_pk_sign(privkey,
Packit Service 31306d
                         md,
Packit Service 31306d
                         digest,
Packit Service 31306d
                         dlen,
Packit Service 31306d
                         sig,
Packit Service 31306d
                         &slen,
Packit Service 31306d
                         mbedtls_ctr_drbg_random,
Packit Service 31306d
                         ssh_get_mbedtls_ctr_drbg_context());
Packit Service 31306d
Packit Service 31306d
    if (ok != 0) {
Packit Service 31306d
        SAFE_FREE(sig);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    sig_blob = ssh_string_new(slen);
Packit Service 31306d
    if (sig_blob == NULL) {
Packit Service 31306d
        SAFE_FREE(sig);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    ssh_string_fill(sig_blob, sig, slen);
Packit Service 31306d
    explicit_bzero(sig, slen);
Packit Service 31306d
    SAFE_FREE(sig);
Packit Service 31306d
Packit Service 31306d
    return sig_blob;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
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_RSA:
Packit Service 31306d
            sig->rsa_sig = rsa_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
Packit Service 31306d
            if (sig->rsa_sig == NULL) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
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
            sig->ecdsa_sig.r = bignum_new();
Packit Service 31306d
            if (sig->ecdsa_sig.r == NULL) {
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            sig->ecdsa_sig.s = bignum_new();
Packit Service 31306d
            if (sig->ecdsa_sig.s == NULL) {
Packit Service 31306d
                bignum_safe_free(sig->ecdsa_sig.r);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            rc = mbedtls_ecdsa_sign(&privkey->ecdsa->grp,
Packit Service 31306d
                                    sig->ecdsa_sig.r,
Packit Service 31306d
                                    sig->ecdsa_sig.s,
Packit Service 31306d
                                    &privkey->ecdsa->d,
Packit Service 31306d
                                    hash,
Packit Service 31306d
                                    hlen,
Packit Service 31306d
                                    mbedtls_ctr_drbg_random,
Packit Service 31306d
                                    ssh_get_mbedtls_ctr_drbg_context());
Packit Service 31306d
            if (rc != 0) {
Packit Service 31306d
                ssh_signature_free(sig);
Packit Service 31306d
                return NULL;
Packit Service 31306d
            }
Packit Service 31306d
            break;
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
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 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
    unsigned char hash[SHA512_DIGEST_LEN] = {0};
Packit Service 31306d
    const unsigned char *sign_input = NULL;
Packit Service 31306d
    uint32_t hlen = 0;
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
    switch (hash_type) {
Packit Service 31306d
    case SSH_DIGEST_SHA256:
Packit Service 31306d
        sha256(input, input_len, hash);
Packit Service 31306d
        hlen = SHA256_DIGEST_LEN;
Packit Service 31306d
        sign_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA384:
Packit Service 31306d
        sha384(input, input_len, hash);
Packit Service 31306d
        hlen = SHA384_DIGEST_LEN;
Packit Service 31306d
        sign_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA512:
Packit Service 31306d
        sha512(input, input_len, hash);
Packit Service 31306d
        hlen = SHA512_DIGEST_LEN;
Packit Service 31306d
        sign_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA1:
Packit Service 31306d
        sha1(input, input_len, hash);
Packit Service 31306d
        hlen = SHA_DIGEST_LEN;
Packit Service 31306d
        sign_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_AUTO:
Packit Service 31306d
        if (privkey->type == SSH_KEYTYPE_ED25519) {
Packit Service 31306d
            /* SSH_DIGEST_AUTO should only be used with ed25519 */
Packit Service 31306d
            sign_input = input;
Packit Service 31306d
            hlen = input_len;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        FALL_THROUGH;
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 pki_do_sign_hash(privkey, sign_input, hlen, hash_type);
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
Packit Service 31306d
    unsigned char hash[SHA512_DIGEST_LEN] = {0};
Packit Service 31306d
    const unsigned char *verify_input = NULL;
Packit Service 31306d
    uint32_t hlen = 0;
Packit Service 31306d
Packit Service 31306d
    mbedtls_md_type_t md = 0;
Packit Service 31306d
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL ||
Packit Service 31306d
        signature == NULL)
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
    switch (signature->hash_type) {
Packit Service 31306d
    case SSH_DIGEST_SHA256:
Packit Service 31306d
        sha256(input, input_len, hash);
Packit Service 31306d
        hlen = SHA256_DIGEST_LEN;
Packit Service 31306d
        md = MBEDTLS_MD_SHA256;
Packit Service 31306d
        verify_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA384:
Packit Service 31306d
        sha384(input, input_len, hash);
Packit Service 31306d
        hlen = SHA384_DIGEST_LEN;
Packit Service 31306d
        md = MBEDTLS_MD_SHA384;
Packit Service 31306d
        verify_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA512:
Packit Service 31306d
        sha512(input, input_len, hash);
Packit Service 31306d
        hlen = SHA512_DIGEST_LEN;
Packit Service 31306d
        md = MBEDTLS_MD_SHA512;
Packit Service 31306d
        verify_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_SHA1:
Packit Service 31306d
        sha1(input, input_len, hash);
Packit Service 31306d
        hlen = SHA_DIGEST_LEN;
Packit Service 31306d
        md = MBEDTLS_MD_SHA1;
Packit Service 31306d
        verify_input = hash;
Packit Service 31306d
        break;
Packit Service 31306d
    case SSH_DIGEST_AUTO:
Packit Service 31306d
        if (pubkey->type == SSH_KEYTYPE_ED25519 ||
Packit Service 31306d
            pubkey->type == SSH_KEYTYPE_ED25519_CERT01)
Packit Service 31306d
        {
Packit Service 31306d
            verify_input = input;
Packit Service 31306d
            hlen = input_len;
Packit Service 31306d
            break;
Packit Service 31306d
        }
Packit Service 31306d
        FALL_THROUGH;
Packit Service 31306d
    default:
Packit Service 31306d
        SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d",
Packit Service 31306d
                signature->hash_type);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    switch (pubkey->type) {
Packit Service 31306d
        case SSH_KEYTYPE_RSA:
Packit Service 31306d
        case SSH_KEYTYPE_RSA_CERT01:
Packit Service 31306d
            rc = mbedtls_pk_verify(pubkey->rsa, md, hash, hlen,
Packit Service 31306d
                    ssh_string_data(signature->rsa_sig),
Packit Service 31306d
                    ssh_string_len(signature->rsa_sig));
Packit Service 31306d
            if (rc != 0) {
Packit Service 31306d
                char error_buf[100];
Packit Service 31306d
                mbedtls_strerror(rc, error_buf, 100);
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE, "RSA error: %s", error_buf);
Packit Service 31306d
                return SSH_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
            rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->grp, hash, hlen,
Packit Service 31306d
                    &pubkey->ecdsa->Q, signature->ecdsa_sig.r,
Packit Service 31306d
                    signature->ecdsa_sig.s);
Packit Service 31306d
            if (rc != 0) {
Packit Service 31306d
                char error_buf[100];
Packit Service 31306d
                mbedtls_strerror(rc, error_buf, 100);
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE, "ECDSA error: %s", error_buf);
Packit Service 31306d
                return SSH_ERROR;
Packit Service 31306d
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_KEYTYPE_ED25519:
Packit Service 31306d
        case SSH_KEYTYPE_ED25519_CERT01:
Packit Service 31306d
            rc = pki_ed25519_verify(pubkey, signature, verify_input, hlen);
Packit Service 31306d
            if (rc != SSH_OK) {
Packit Service 31306d
                SSH_LOG(SSH_LOG_TRACE, "ED25519 error: Signature invalid");
Packit Service 31306d
                return SSH_ERROR;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            SSH_LOG(SSH_LOG_TRACE, "Unknown public key type");
Packit Service 31306d
            return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
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_mbedtls_nistp256:
Packit Service 31306d
            return "ecdsa-sha2-nistp256";
Packit Service 31306d
        case NID_mbedtls_nistp384:
Packit Service 31306d
            return "ecdsa-sha2-nistp384";
Packit Service 31306d
        case NID_mbedtls_nistp521:
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
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_mbedtls_nistp256;
Packit Service 31306d
    } else if (strcmp(name, "nistp384") == 0) {
Packit Service 31306d
        return NID_mbedtls_nistp384;
Packit Service 31306d
    } else if (strcmp(name, "nistp521") == 0) {
Packit Service 31306d
        return NID_mbedtls_nistp521;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid)
Packit Service 31306d
{
Packit Service 31306d
    switch (nid) {
Packit Service 31306d
        case NID_mbedtls_nistp256:
Packit Service 31306d
            return MBEDTLS_ECP_DP_SECP256R1;
Packit Service 31306d
        case NID_mbedtls_nistp384:
Packit Service 31306d
            return MBEDTLS_ECP_DP_SECP384R1;
Packit Service 31306d
        case NID_mbedtls_nistp521:
Packit Service 31306d
            return MBEDTLS_ECP_DP_SECP521R1;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return MBEDTLS_ECP_DP_NONE;
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
    int rc;
Packit Service 31306d
    mbedtls_ecp_keypair keypair;
Packit Service 31306d
    mbedtls_ecp_group group;
Packit Service 31306d
    mbedtls_ecp_point Q;
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 = malloc(sizeof(mbedtls_ecdsa_context));
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_ecdsa_init(key->ecdsa);
Packit Service 31306d
    mbedtls_ecp_keypair_init(&keypair);
Packit Service 31306d
    mbedtls_ecp_group_init(&group);
Packit Service 31306d
    mbedtls_ecp_point_init(&Q);
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_group_load(&group,
Packit Service 31306d
                                pki_key_ecdsa_nid_to_mbed_gid(nid));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
Packit Service 31306d
                                       ssh_string_len(e));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_copy(&keypair.Q, &Q);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp),
Packit Service 31306d
                                 ssh_string_len(exp));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_ecp_point_free(&Q);
Packit Service 31306d
    mbedtls_ecp_group_free(&group);
Packit Service 31306d
    mbedtls_ecp_keypair_free(&keypair);
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
Packit Service 31306d
fail:
Packit Service 31306d
    mbedtls_ecdsa_free(key->ecdsa);
Packit Service 31306d
    mbedtls_ecp_point_free(&Q);
Packit Service 31306d
    mbedtls_ecp_group_free(&group);
Packit Service 31306d
    mbedtls_ecp_keypair_free(&keypair);
Packit Service 31306d
    SAFE_FREE(key->ecdsa);
Packit Service 31306d
    return SSH_ERROR;
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
    int rc;
Packit Service 31306d
    mbedtls_ecp_keypair keypair;
Packit Service 31306d
    mbedtls_ecp_group group;
Packit Service 31306d
    mbedtls_ecp_point Q;
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 = malloc(sizeof(mbedtls_ecdsa_context));
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_ecdsa_init(key->ecdsa);
Packit Service 31306d
    mbedtls_ecp_keypair_init(&keypair);
Packit Service 31306d
    mbedtls_ecp_group_init(&group);
Packit Service 31306d
    mbedtls_ecp_point_init(&Q);
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_group_load(&group,
Packit Service 31306d
            pki_key_ecdsa_nid_to_mbed_gid(nid));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e),
Packit Service 31306d
            ssh_string_len(e));
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_copy(&keypair.Q, &Q);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecp_group_copy(&keypair.grp, &group);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_mpi_init(&keypair.d);
Packit Service 31306d
Packit Service 31306d
    rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
Packit Service 31306d
    if (rc != 0) {
Packit Service 31306d
        goto fail;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_ecp_point_free(&Q);
Packit Service 31306d
    mbedtls_ecp_group_free(&group);
Packit Service 31306d
    mbedtls_ecp_keypair_free(&keypair);
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
fail:
Packit Service 31306d
    mbedtls_ecdsa_free(key->ecdsa);
Packit Service 31306d
    mbedtls_ecp_point_free(&Q);
Packit Service 31306d
    mbedtls_ecp_group_free(&group);
Packit Service 31306d
    mbedtls_ecp_keypair_free(&keypair);
Packit Service 31306d
    SAFE_FREE(key->ecdsa);
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_generate_ecdsa(ssh_key key, int parameter)
Packit Service 31306d
{
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_mbedtls_nistp384;
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_mbedtls_nistp521;
Packit Service 31306d
            key->type = SSH_KEYTYPE_ECDSA_P521;
Packit Service 31306d
            break;
Packit Service 31306d
        case 256:
Packit Service 31306d
        default:
Packit Service 31306d
            key->ecdsa_nid = NID_mbedtls_nistp256;
Packit Service 31306d
            key->type = SSH_KEYTYPE_ECDSA_P256;
Packit Service 31306d
            break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
Packit Service 31306d
    if (key->ecdsa == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    mbedtls_ecdsa_init(key->ecdsa);
Packit Service 31306d
Packit Service 31306d
    ok = mbedtls_ecdsa_genkey(key->ecdsa,
Packit Service 31306d
                              pki_key_ecdsa_nid_to_mbed_gid(key->ecdsa_nid),
Packit Service 31306d
                              mbedtls_ctr_drbg_random,
Packit Service 31306d
                              ssh_get_mbedtls_ctr_drbg_context());
Packit Service 31306d
Packit Service 31306d
    if (ok != 0) {
Packit Service 31306d
        mbedtls_ecdsa_free(key->ecdsa);
Packit Service 31306d
        SAFE_FREE(key->ecdsa);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
Packit Service 31306d
        ssh_string pubkey, ssh_string privkey)
Packit Service 31306d
{
Packit Service 31306d
    (void) key;
Packit Service 31306d
    (void) p;
Packit Service 31306d
    (void) q;
Packit Service 31306d
    (void) g;
Packit Service 31306d
    (void) pubkey;
Packit Service 31306d
    (void) privkey;
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g,
Packit Service 31306d
        ssh_string pubkey)
Packit Service 31306d
{
Packit Service 31306d
    (void) key;
Packit Service 31306d
    (void) p;
Packit Service 31306d
    (void) q;
Packit Service 31306d
    (void) g;
Packit Service 31306d
    (void) pubkey;
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int pki_key_generate_dss(ssh_key key, int parameter)
Packit Service 31306d
{
Packit Service 31306d
    (void) key;
Packit Service 31306d
    (void) parameter;
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
#endif /* HAVE_LIBMBEDCRYPTO */