Blame src/pki_ed25519.c

Packit 6c0a39
/*
Packit 6c0a39
 * pki_ed25519 .c - PKI infrastructure using ed25519
Packit 6c0a39
 *
Packit 6c0a39
 * This file is part of the SSH Library
Packit 6c0a39
 *
Packit 6c0a39
 * Copyright (c) 2014 by Aris Adamantiadis
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is free software; you can redistribute it and/or modify
Packit 6c0a39
 * it under the terms of the GNU Lesser General Public License as published by
Packit 6c0a39
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit 6c0a39
 * option) any later version.
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is distributed in the hope that it will be useful, but
Packit 6c0a39
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 6c0a39
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit 6c0a39
 * License for more details.
Packit 6c0a39
 *
Packit 6c0a39
 * You should have received a copy of the GNU Lesser General Public License
Packit 6c0a39
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit 6c0a39
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit 6c0a39
 * MA 02111-1307, USA.
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
#include "config.h"
Packit 6c0a39
Packit 6c0a39
#include "libssh/pki.h"
Packit 6c0a39
#include "libssh/pki_priv.h"
Packit 6c0a39
#include "libssh/ed25519.h"
Packit 6c0a39
#include "libssh/buffer.h"
Packit 6c0a39
Packit 6c0a39
int pki_key_generate_ed25519(ssh_key key)
Packit 6c0a39
{
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    key->ed25519_privkey = malloc(sizeof (ed25519_privkey));
Packit 6c0a39
    if (key->ed25519_privkey == NULL) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    key->ed25519_pubkey = malloc(sizeof (ed25519_pubkey));
Packit 6c0a39
    if (key->ed25519_pubkey == NULL) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    rc = crypto_sign_ed25519_keypair(*key->ed25519_pubkey,
Packit 6c0a39
                                     *key->ed25519_privkey);
Packit 6c0a39
    if (rc != 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    return SSH_OK;
Packit 6c0a39
error:
Packit 6c0a39
    SAFE_FREE(key->ed25519_privkey);
Packit 6c0a39
    SAFE_FREE(key->ed25519_pubkey);
Packit 6c0a39
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int pki_ed25519_sign(const ssh_key privkey,
Packit 6c0a39
                     ssh_signature sig,
Packit 6c0a39
                     const unsigned char *hash,
Packit 6c0a39
                     size_t hlen)
Packit 6c0a39
{
Packit 6c0a39
    int rc;
Packit 6c0a39
    uint8_t *buffer;
Packit 6c0a39
    uint64_t dlen = 0;
Packit 6c0a39
Packit 6c0a39
    buffer = malloc(hlen + ED25519_SIG_LEN);
Packit 6c0a39
    if (buffer == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    rc = crypto_sign_ed25519(buffer,
Packit 6c0a39
                             &dlen,
Packit 6c0a39
                             hash,
Packit 6c0a39
                             hlen,
Packit 6c0a39
                             *privkey->ed25519_privkey);
Packit 6c0a39
    if (rc != 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    /* This shouldn't happen */
Packit 6c0a39
    if (dlen - hlen != ED25519_SIG_LEN) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    sig->ed25519_sig = malloc(ED25519_SIG_LEN);
Packit 6c0a39
    if (sig->ed25519_sig == NULL) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    memcpy(sig->ed25519_sig, buffer, ED25519_SIG_LEN);
Packit 6c0a39
    SAFE_FREE(buffer);
Packit 6c0a39
Packit 6c0a39
    return SSH_OK;
Packit 6c0a39
error:
Packit 6c0a39
    SAFE_FREE(buffer);
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int pki_ed25519_verify(const ssh_key pubkey,
Packit 6c0a39
                       ssh_signature sig,
Packit 6c0a39
                       const unsigned char *hash,
Packit 6c0a39
                       size_t hlen)
Packit 6c0a39
{
Packit 6c0a39
    uint64_t mlen = 0;
Packit 6c0a39
    uint8_t *buffer;
Packit 6c0a39
    uint8_t *buffer2;
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    if (pubkey == NULL || sig == NULL ||
Packit 6c0a39
        hash == NULL || sig->ed25519_sig == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    buffer = malloc(hlen + ED25519_SIG_LEN);
Packit 6c0a39
    if (buffer == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    buffer2 = malloc(hlen + ED25519_SIG_LEN);
Packit 6c0a39
    if (buffer2 == NULL) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    memcpy(buffer, sig->ed25519_sig, ED25519_SIG_LEN);
Packit 6c0a39
    memcpy(buffer + ED25519_SIG_LEN, hash, hlen);
Packit 6c0a39
Packit 6c0a39
    rc = crypto_sign_ed25519_open(buffer2,
Packit 6c0a39
                                  &mlen,
Packit 6c0a39
                                  buffer,
Packit 6c0a39
                                  hlen + ED25519_SIG_LEN,
Packit 6c0a39
                                  *pubkey->ed25519_pubkey);
Packit 6c0a39
Packit 6c0a39
    explicit_bzero(buffer, hlen + ED25519_SIG_LEN);
Packit 6c0a39
    explicit_bzero(buffer2, hlen);
Packit 6c0a39
    SAFE_FREE(buffer);
Packit 6c0a39
    SAFE_FREE(buffer2);
Packit 6c0a39
    if (rc == 0) {
Packit 6c0a39
        return SSH_OK;
Packit 6c0a39
    } else {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
error:
Packit 6c0a39
    SAFE_FREE(buffer);
Packit 6c0a39
    SAFE_FREE(buffer2);
Packit 6c0a39
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39