/* $OpenBSD: ssh-pkcs11-client.c,v 1.2 2010/02/24 06:12:53 djm Exp $ */
/*
 * Copyright (c) 2010 Markus Friedl.  All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "includes.h"

#ifdef ENABLE_PKCS11

#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/socket.h>

#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "pathnames.h"
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "key.h"
#include "authfd.h"
#include "atomicio.h"
#include "ssh-pkcs11.h"

/* borrows code from sftp-server and ssh-agent */

int fd = -1;
pid_t pid = -1;

static void
send_msg(Buffer *m)
{
	u_char buf[4];
	int mlen = buffer_len(m);

	put_u32(buf, mlen);
	if (atomicio(vwrite, fd, buf, 4) != 4 ||
	    atomicio(vwrite, fd, buffer_ptr(m),
	    buffer_len(m)) != buffer_len(m))
		error("write to helper failed");
	buffer_consume(m, mlen);
}

static int
recv_msg(Buffer *m)
{
	u_int l, len;
	u_char buf[1024];

	if ((len = atomicio(read, fd, buf, 4)) != 4) {
		error("read from helper failed: %u", len);
		return (0); /* XXX */
	}
	len = get_u32(buf);
	if (len > 256 * 1024)
		fatal("response too long: %u", len);
	/* read len bytes into m */
	buffer_clear(m);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		if (atomicio(read, fd, buf, l) != l) {
			error("response from helper failed.");
			return (0); /* XXX */
		}
		buffer_append(m, buf, l);
		len -= l;
	}
	return (buffer_get_char(m));
}

int
pkcs11_init(int interactive)
{
	return (0);
}

void
pkcs11_terminate(void)
{
	close(fd);
}

static int
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
    int padding)
{
	Key key;
	u_char *blob, *signature = NULL;
	u_int blen, slen = 0;
	int ret = -1;
	Buffer msg;

	if (padding != RSA_PKCS1_PADDING)
		return (-1);
	key.type = KEY_RSA;
	key.rsa = rsa;
	if (key_to_blob(&key, &blob, &blen) == 0)
		return -1;
	buffer_init(&msg);
	buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
	buffer_put_string(&msg, blob, blen);
	buffer_put_string(&msg, from, flen);
	buffer_put_int(&msg, 0);
	xfree(blob);
	send_msg(&msg);

	if (recv_msg(&msg) == SSH2_AGENT_SIGN_RESPONSE) {
		signature = buffer_get_string(&msg, &slen);
		if (slen <= (u_int)RSA_size(rsa)) {
			memcpy(to, signature, slen);
			ret = slen;
		}
		xfree(signature);
	}
	return (ret);
}

/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
static int
wrap_key(RSA *rsa)
{
	static RSA_METHOD helper_rsa;

	memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa));
	helper_rsa.name = "ssh-pkcs11-helper";
	helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt;
	RSA_set_method(rsa, &helper_rsa);
	return (0);
}

static int
pkcs11_start_helper(void)
{
	int pair[2];

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
		error("socketpair: %s", strerror(errno));
		return (-1);
	}
	if ((pid = fork()) == -1) {
		error("fork: %s", strerror(errno));
		return (-1);
	} else if (pid == 0) {
		if ((dup2(pair[1], STDIN_FILENO) == -1) ||
		    (dup2(pair[1], STDOUT_FILENO) == -1)) {
			fprintf(stderr, "dup2: %s\n", strerror(errno));
			_exit(1);
		}
		close(pair[0]);
		close(pair[1]);
		execlp(_PATH_SSH_PKCS11_HELPER, _PATH_SSH_PKCS11_HELPER,
		    (char *) 0);
		fprintf(stderr, "exec: %s: %s\n", _PATH_SSH_PKCS11_HELPER,
		    strerror(errno));
		_exit(1);
	}
	close(pair[1]);
	fd = pair[0];
	return (0);
}

int
pkcs11_add_provider(char *name, char *pin, Key ***keysp)
{
	Key *k;
	int i, nkeys;
	u_char *blob;
	u_int blen;
	Buffer msg;

	if (fd < 0 && pkcs11_start_helper() < 0)
		return (-1);

	buffer_init(&msg);
	buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY);
	buffer_put_cstring(&msg, name);
	buffer_put_cstring(&msg, pin);
	send_msg(&msg);
	buffer_clear(&msg);

	if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
		nkeys = buffer_get_int(&msg);
		*keysp = xcalloc(nkeys, sizeof(Key *));
		for (i = 0; i < nkeys; i++) {
			blob = buffer_get_string(&msg, &blen);
			xfree(buffer_get_string(&msg, NULL));
			k = key_from_blob(blob, blen);
			wrap_key(k->rsa);
			(*keysp)[i] = k;
			xfree(blob);
		}
	} else {
		nkeys = -1;
	}
	buffer_free(&msg);
	return (nkeys);
}

int
pkcs11_del_provider(char *name)
{
	int ret = -1;
	Buffer msg;

	buffer_init(&msg);
	buffer_put_char(&msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY);
	buffer_put_cstring(&msg, name);
	buffer_put_cstring(&msg, "");
	send_msg(&msg);
	buffer_clear(&msg);

	if (recv_msg(&msg) == SSH_AGENT_SUCCESS)
		ret = 0;
	buffer_free(&msg);
	return (ret);
}

#endif /* ENABLE_PKCS11 */
