blob: 22e52c97a39102e48a967e4619026640e24818c2 [file] [log] [blame]
Randall Spangler32a65262011-06-27 10:49:11 -07001/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Randall Spanglerd1836442010-06-10 09:59:04 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Host functions for signature generation.
6 */
7
8/* TODO: change all 'return 0', 'return 1' into meaningful return codes */
9
Randall Spanglerd1836442010-06-10 09:59:04 -070010#include <openssl/rsa.h>
11
12#include <stdio.h>
13#include <stdlib.h>
Gaurav Shah068fc6f2010-10-29 10:59:50 -070014#include <sys/types.h>
15#include <sys/wait.h>
Randall Spanglerd1836442010-06-10 09:59:04 -070016#include <unistd.h>
17
Randall Spangler7c3ae422016-05-11 13:50:18 -070018#include "2sysincludes.h"
19
20#include "2common.h"
Randall Spangler7d0cc742016-06-30 11:30:32 -070021#include "2rsa.h"
Randall Spangler7c3ae422016-05-11 13:50:18 -070022#include "2sha.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070023#include "host_common.h"
Randall Spangler7d0cc742016-06-30 11:30:32 -070024#include "host_signature2.h"
25#include "vb2_common.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070026
Randall Spangler7d0cc742016-06-30 11:30:32 -070027/* Invoke [external_signer] command with [pem_file] as an argument, contents of
28 * [inbuf] passed redirected to stdin, and the stdout of the command is put
29 * back into [outbuf]. Returns -1 on error, 0 on success.
Gaurav Shah068fc6f2010-10-29 10:59:50 -070030 */
Randall Spangler7d0cc742016-06-30 11:30:32 -070031static int sign_external(uint32_t size,
32 const uint8_t *inbuf,
33 uint8_t *outbuf,
34 uint32_t outbufsize,
35 const char *pem_file,
36 const char *external_signer)
37{
38 int rv = 0, n;
39 int p_to_c[2], c_to_p[2]; /* pipe descriptors */
40 pid_t pid;
Gaurav Shah068fc6f2010-10-29 10:59:50 -070041
Randall Spangler7d0cc742016-06-30 11:30:32 -070042 VB2_DEBUG("Will invoke \"%s %s\" to perform signing.\n"
43 "Input to the signer will be provided on standard in.\n"
44 "Output of the signer will be read from standard out.\n",
45 external_signer, pem_file);
Gaurav Shah068fc6f2010-10-29 10:59:50 -070046
Randall Spangler7d0cc742016-06-30 11:30:32 -070047 /* Need two pipes since we want to invoke the external_signer as
48 * a co-process writing to its stdin and reading from its stdout. */
49 if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) {
50 VB2_DEBUG("pipe() error\n");
51 return -1;
52 }
53 if ((pid = fork()) < 0) {
54 VB2_DEBUG("fork() error\n");
55 return -1;
56 } else if (pid > 0) { /* Parent. */
57 close(p_to_c[STDIN_FILENO]);
58 close(c_to_p[STDOUT_FILENO]);
Gaurav Shah068fc6f2010-10-29 10:59:50 -070059
Randall Spangler7d0cc742016-06-30 11:30:32 -070060 /* We provide input to the child process (external signer). */
61 if (write(p_to_c[STDOUT_FILENO], inbuf, size) != size) {
62 VB2_DEBUG("write() error\n");
63 rv = -1;
64 } else {
65 /* Send EOF to child (signer process). */
66 close(p_to_c[STDOUT_FILENO]);
Gaurav Shah068fc6f2010-10-29 10:59:50 -070067
Randall Spangler7d0cc742016-06-30 11:30:32 -070068 do {
69 n = read(c_to_p[STDIN_FILENO], outbuf,
70 outbufsize);
71 outbuf += n;
72 outbufsize -= n;
73 } while (n > 0 && outbufsize);
Gaurav Shah068fc6f2010-10-29 10:59:50 -070074
Randall Spangler7d0cc742016-06-30 11:30:32 -070075 if (n < 0) {
76 VB2_DEBUG("read() error\n");
77 rv = -1;
78 }
79 }
80 if (waitpid(pid, NULL, 0) < 0) {
81 VB2_DEBUG("waitpid() error\n");
82 rv = -1;
83 }
84 } else { /* Child. */
85 close (p_to_c[STDOUT_FILENO]);
86 close (c_to_p[STDIN_FILENO]);
87 /* Map the stdin to the first pipe (this pipe gets input
88 * from the parent) */
89 if (STDIN_FILENO != p_to_c[STDIN_FILENO]) {
90 if (dup2(p_to_c[STDIN_FILENO], STDIN_FILENO) !=
91 STDIN_FILENO) {
92 VB2_DEBUG("stdin dup2() failed\n");
93 close(p_to_c[0]);
94 return -1;
95 }
96 }
97 /* Map the stdout to the second pipe (this pipe sends back
98 * signer output to the parent) */
99 if (STDOUT_FILENO != c_to_p[STDOUT_FILENO]) {
100 if (dup2(c_to_p[STDOUT_FILENO], STDOUT_FILENO) !=
101 STDOUT_FILENO) {
102 VB2_DEBUG("stdout dup2() failed\n");
103 close(c_to_p[STDOUT_FILENO]);
104 return -1;
105 }
106 }
107 /* External signer is invoked here. */
108 if (execl(external_signer, external_signer, pem_file,
109 (char *) 0) < 0) {
110 VB2_DEBUG("execl() of external signer failed\n");
111 }
112 }
113 return rv;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700114}
115
Randall Spangler7d0cc742016-06-30 11:30:32 -0700116struct vb2_signature *vb2_external_signature(const uint8_t *data,
117 uint32_t size,
118 const char *key_file,
119 uint32_t key_algorithm,
120 const char *external_signer)
121{
122 int vb2_alg = vb2_crypto_to_hash(key_algorithm);
123 uint8_t digest[VB2_MAX_DIGEST_SIZE];
124 int digest_size = vb2_digest_size(vb2_alg);
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700125
Randall Spangler7d0cc742016-06-30 11:30:32 -0700126 uint32_t digest_info_size = 0;
127 const uint8_t *digest_info = NULL;
128 if (VB2_SUCCESS != vb2_digest_info(vb2_alg,
129 &digest_info, &digest_info_size))
130 return NULL;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700131
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700132
Randall Spangler7d0cc742016-06-30 11:30:32 -0700133 uint8_t *signature_digest;
134 uint64_t signature_digest_len = digest_size + digest_info_size;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700135
Randall Spangler7d0cc742016-06-30 11:30:32 -0700136 int rv;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700137
Randall Spangler7d0cc742016-06-30 11:30:32 -0700138 /* Calculate the digest */
139 if (VB2_SUCCESS != vb2_digest_buffer(data, size, vb2_alg,
140 digest, sizeof(digest)))
141 return NULL;
Randall Spangler7c3ae422016-05-11 13:50:18 -0700142
Randall Spangler7d0cc742016-06-30 11:30:32 -0700143 /* Prepend the digest info to the digest */
144 signature_digest = calloc(signature_digest_len, 1);
145 if (!signature_digest)
146 return NULL;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700147
Randall Spangler7d0cc742016-06-30 11:30:32 -0700148 memcpy(signature_digest, digest_info, digest_info_size);
149 memcpy(signature_digest + digest_info_size, digest, digest_size);
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700150
Randall Spangler7d0cc742016-06-30 11:30:32 -0700151 /* Allocate output signature */
152 uint32_t sig_size =
153 vb2_rsa_sig_size(vb2_crypto_to_signature(key_algorithm));
154 struct vb2_signature *sig = vb2_alloc_signature(sig_size, size);
155 if (!sig) {
156 free(signature_digest);
157 return NULL;
158 }
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700159
Randall Spangler7d0cc742016-06-30 11:30:32 -0700160 /* Sign the signature_digest into our output buffer */
161 rv = sign_external(signature_digest_len, /* Input length */
162 signature_digest, /* Input data */
163 vb2_signature_data(sig), /* Output sig */
164 sig_size, /* Max Output sig size */
165 key_file, /* Key file to use */
166 external_signer); /* External cmd to invoke */
167 free(signature_digest);
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700168
Randall Spangler7d0cc742016-06-30 11:30:32 -0700169 if (-1 == rv) {
170 VB2_DEBUG("RSA_private_encrypt() failed.\n");
171 free(sig);
172 return NULL;
173 }
174
175 /* Return the signature */
176 return sig;
Gaurav Shah068fc6f2010-10-29 10:59:50 -0700177}