/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Host functions for signature generation.
 */

/* TODO: change all 'return 0', 'return 1' into meaningful return codes */

#include <openssl/rsa.h>

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "2common.h"
#include "2rsa.h"
#include "2sha.h"
#include "2sysincludes.h"
#include "host_common.h"
#include "host_signature2.h"
#include "vb2_common.h"

/* Invoke [external_signer] command with [pem_file] as an argument, contents of
 * [inbuf] passed redirected to stdin, and the stdout of the command is put
 * back into [outbuf].  Returns -1 on error, 0 on success.
 */
static int sign_external(uint32_t size, const uint8_t *inbuf, uint8_t *outbuf,
			 uint32_t outbufsize, const char *pem_file,
			 const char *external_signer)
{
	int rv = 0, n;
	int p_to_c[2], c_to_p[2];  /* pipe descriptors */
	pid_t pid;

	VB2_DEBUG("Will invoke \"%s %s\" to perform signing.\n"
		 "Input to the signer will be provided on standard in.\n"
		 "Output of the signer will be read from standard out.\n",
		  external_signer, pem_file);

	/* Need two pipes since we want to invoke the external_signer as
	 * a co-process writing to its stdin and reading from its stdout. */
	if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) {
		VB2_DEBUG("pipe() error\n");
		return -1;
	}
	if ((pid = fork()) < 0) {
		VB2_DEBUG("fork() error\n");
		return -1;
	} else if (pid > 0) {  /* Parent. */
		close(p_to_c[STDIN_FILENO]);
		close(c_to_p[STDOUT_FILENO]);

		/* We provide input to the child process (external signer). */
		if (write(p_to_c[STDOUT_FILENO], inbuf, size) != size) {
			VB2_DEBUG("write() error\n");
			rv = -1;
		} else {
			/* Send EOF to child (signer process). */
			close(p_to_c[STDOUT_FILENO]);

			do {
				n = read(c_to_p[STDIN_FILENO], outbuf,
					 outbufsize);
				outbuf += n;
				outbufsize -= n;
			} while (n > 0 && outbufsize);

			if (n < 0) {
				VB2_DEBUG("read() error\n");
				rv = -1;
			}
		}
		if (waitpid(pid, NULL, 0) < 0) {
			VB2_DEBUG("waitpid() error\n");
			rv = -1;
		}
	} else {  /* Child. */
		close (p_to_c[STDOUT_FILENO]);
		close (c_to_p[STDIN_FILENO]);
		/* Map the stdin to the first pipe (this pipe gets input
		 * from the parent) */
		if (STDIN_FILENO != p_to_c[STDIN_FILENO]) {
			if (dup2(p_to_c[STDIN_FILENO], STDIN_FILENO) !=
			    STDIN_FILENO) {
				VB2_DEBUG("stdin dup2() failed\n");
				close(p_to_c[0]);
				return -1;
			}
		}
		/* Map the stdout to the second pipe (this pipe sends back
		 * signer output to the parent) */
		if (STDOUT_FILENO != c_to_p[STDOUT_FILENO]) {
			if (dup2(c_to_p[STDOUT_FILENO], STDOUT_FILENO) !=
			    STDOUT_FILENO) {
				VB2_DEBUG("stdout dup2() failed\n");
				close(c_to_p[STDOUT_FILENO]);
				return -1;
			}
		}
		/* External signer is invoked here. */
		if (execl(external_signer, external_signer, pem_file,
			  (char *) 0) < 0) {
			VB2_DEBUG("execl() of external signer failed\n");
		}
	}
	return rv;
}

struct vb2_signature *vb2_external_signature(const uint8_t *data, uint32_t size,
					     const char *key_file,
					     uint32_t key_algorithm,
					     const char *external_signer)
{
	int vb2_alg = vb2_crypto_to_hash(key_algorithm);
	uint8_t digest[VB2_MAX_DIGEST_SIZE];
	int digest_size = vb2_digest_size(vb2_alg);

	uint32_t digest_info_size = 0;
	const uint8_t *digest_info = NULL;
	if (VB2_SUCCESS != vb2_digest_info(vb2_alg,
					   &digest_info, &digest_info_size))
		return NULL;


	uint8_t *signature_digest;
	uint64_t signature_digest_len = digest_size + digest_info_size;

	int rv;

	/* Calculate the digest */
	if (VB2_SUCCESS != vb2_digest_buffer(data, size, vb2_alg,
					     digest, sizeof(digest)))
		return NULL;

	/* Prepend the digest info to the digest */
	signature_digest = calloc(signature_digest_len, 1);
	if (!signature_digest)
		return NULL;

	memcpy(signature_digest, digest_info, digest_info_size);
	memcpy(signature_digest + digest_info_size, digest, digest_size);

	/* Allocate output signature */
	uint32_t sig_size =
		vb2_rsa_sig_size(vb2_crypto_to_signature(key_algorithm));
	struct vb2_signature *sig = vb2_alloc_signature(sig_size, size);
	if (!sig) {
		free(signature_digest);
		return NULL;
	}

	/* Sign the signature_digest into our output buffer */
	rv = sign_external(signature_digest_len,    /* Input length */
			   signature_digest,        /* Input data */
			   vb2_signature_data(sig), /* Output sig */
			   sig_size,                /* Max Output sig size */
			   key_file,                /* Key file to use */
			   external_signer);        /* External cmd to invoke */
	free(signature_digest);

	if (-1 == rv) {
		VB2_DEBUG("RSA_private_encrypt() failed.\n");
		free(sig);
		return NULL;
	}

	/* Return the signature */
	return sig;
}
