/* 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 "2sysincludes.h"

#include "2common.h"
#include "2sha.h"
#include "cryptolib.h"
#include "file_keys.h"
#include "host_common.h"
#include "vboot_common.h"


VbSignature* SignatureAlloc(uint64_t sig_size, uint64_t data_size) {
  VbSignature* sig = (VbSignature*)malloc(sizeof(VbSignature) + sig_size);
  if (!sig)
    return NULL;

  sig->sig_offset = sizeof(VbSignature);
  sig->sig_size = sig_size;
  sig->data_size = data_size;
  return sig;
}


void SignatureInit(VbSignature* sig, uint8_t* sig_data,
                   uint64_t sig_size, uint64_t data_size) {
  sig->sig_offset = OffsetOf(sig, sig_data);
  sig->sig_size = sig_size;
  sig->data_size = data_size;
}


int SignatureCopy(VbSignature* dest, const VbSignature* src) {
  if (dest->sig_size < src->sig_size)
    return 1;
  dest->sig_size = src->sig_size;
  dest->data_size = src->data_size;
  Memcpy(GetSignatureData(dest), GetSignatureDataC(src), src->sig_size);
  return 0;
}

VbSignature* CalculateSignature(const uint8_t* data, uint64_t size,
                                const VbPrivateKey* key) {
  int vb2_alg = vb2_crypto_to_hash(key->algorithm);
  uint8_t digest[VB2_MAX_DIGEST_SIZE];
  int digest_size = vb2_digest_size(vb2_alg);

  const uint8_t* digestinfo = hash_digestinfo_map[key->algorithm];
  int digestinfo_size = digestinfo_size_map[key->algorithm];

  uint8_t* signature_digest;
  int signature_digest_len = digest_size + digestinfo_size;

  VbSignature* sig;
  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 = malloc(signature_digest_len);
  if (!signature_digest)
    return NULL;

  Memcpy(signature_digest, digestinfo, digestinfo_size);
  Memcpy(signature_digest + digestinfo_size, digest, digest_size);

  /* Allocate output signature */
  sig = SignatureAlloc(siglen_map[key->algorithm], size);
  if (!sig) {
    free(signature_digest);
    return NULL;
  }

  /* Sign the signature_digest into our output buffer */
  rv = RSA_private_encrypt(signature_digest_len,   /* Input length */
                           signature_digest,       /* Input data */
                           GetSignatureData(sig),  /* Output sig */
                           key->rsa_private_key,   /* Key to use */
                           RSA_PKCS1_PADDING);     /* Padding to use */
  free(signature_digest);

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

  /* Return the signature */
  return sig;
}

/* 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.
 */
int InvokeExternalSigner(uint64_t size,
                         const uint8_t* inbuf,
                         uint8_t* outbuf,
                         uint64_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;

  VBDEBUG(("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) {
    VBDEBUG(("pipe() error\n"));
    return -1;
  }
  if ((pid = fork()) < 0) {
    VBDEBUG(("fork() error"));
    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) {
      VBDEBUG(("write() error while providing input to external signer\n"));
      rv = -1;
    } else {
      close(p_to_c[STDOUT_FILENO]);  /* Send EOF to child (signer process). */
      do {
        n = read(c_to_p[STDIN_FILENO], outbuf, outbufsize);
        outbuf += n;
        outbufsize -= n;
      } while (n > 0 && outbufsize);

      if (n < 0) {
        VBDEBUG(("read() error while reading output from external signer\n"));
        rv = -1;
      }
    }
    if (waitpid(pid, NULL, 0) < 0) {
      VBDEBUG(("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) {
        VBDEBUG(("stdin dup2() failed (external signer)\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) {
        VBDEBUG(("stdout dup2() failed (external signer)\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) {
      VBDEBUG(("execl() of external signer failed\n"));
    }
  }
  return rv;
}

/* TODO(gauravsh): This could easily be integrated into CalculateSignature()
 * since the code is almost a mirror - I have kept it as such to avoid changing
 * the existing interface. */
VbSignature* CalculateSignature_external(const uint8_t* data, uint64_t size,
                                         const char* key_file,
                                         uint64_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);

  const uint8_t* digestinfo = hash_digestinfo_map[key_algorithm];
  uint64_t digestinfo_size = digestinfo_size_map[key_algorithm];

  uint8_t* signature_digest;
  uint64_t signature_digest_len = digest_size + digestinfo_size;

  VbSignature* sig;
  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 = malloc(signature_digest_len);
  if (!signature_digest)
    return NULL;

  Memcpy(signature_digest, digestinfo, digestinfo_size);
  Memcpy(signature_digest + digestinfo_size, digest, digest_size);

  /* Allocate output signature */
  sig = SignatureAlloc(siglen_map[key_algorithm], size);
  if (!sig) {
    free(signature_digest);
    return NULL;
  }

  /* Sign the signature_digest into our output buffer */
  rv = InvokeExternalSigner(signature_digest_len, /* Input length */
                            signature_digest,     /* Input data */
                            GetSignatureData(sig), /* Output sig */
                            siglen_map[key_algorithm], /* Max Output sig size */
                            key_file,             /* Key file to use */
                            external_signer);     /* External cmd to invoke */
  free(signature_digest);

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

  /* Return the signature */
  return sig;
}
