123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /* 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 "2rsa.h"
- #include "2sha.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;
- }
|