1 /* Copyright 2011 The ChromiumOS Authors
2 * 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
10 #include <openssl/rsa.h>
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17
18 #include "2common.h"
19 #include "2rsa.h"
20 #include "2sha.h"
21 #include "2sysincludes.h"
22 #include "host_common.h"
23 #include "host_signature21.h"
24
25 /* Invoke [external_signer] command with [pem_file] as an argument, contents of
26 * [inbuf] passed redirected to stdin, and the stdout of the command is put
27 * back into [outbuf]. Returns -1 on error, 0 on success.
28 */
sign_external(uint32_t size,const uint8_t * inbuf,uint8_t * outbuf,uint32_t outbufsize,const char * pem_file,const char * external_signer)29 static int sign_external(uint32_t size, const uint8_t *inbuf, uint8_t *outbuf,
30 uint32_t outbufsize, const char *pem_file,
31 const char *external_signer)
32 {
33 int rv = 0, n;
34 int p_to_c[2], c_to_p[2]; /* pipe descriptors */
35 pid_t pid;
36
37 VB2_DEBUG("Will invoke \"%s %s\" to perform signing.\n"
38 "Input to the signer will be provided on standard in.\n"
39 "Output of the signer will be read from standard out.\n",
40 external_signer, pem_file);
41
42 /* Need two pipes since we want to invoke the external_signer as
43 * a co-process writing to its stdin and reading from its stdout. */
44 if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) {
45 VB2_DEBUG("pipe() error\n");
46 return -1;
47 }
48 if ((pid = fork()) < 0) {
49 VB2_DEBUG("fork() error\n");
50 return -1;
51 } else if (pid > 0) { /* Parent. */
52 close(p_to_c[STDIN_FILENO]);
53 close(c_to_p[STDOUT_FILENO]);
54
55 /* We provide input to the child process (external signer). */
56 if (write(p_to_c[STDOUT_FILENO], inbuf, size) != size) {
57 VB2_DEBUG("write() error\n");
58 rv = -1;
59 } else {
60 /* Send EOF to child (signer process). */
61 close(p_to_c[STDOUT_FILENO]);
62
63 do {
64 n = read(c_to_p[STDIN_FILENO], outbuf,
65 outbufsize);
66 outbuf += n;
67 outbufsize -= n;
68 } while (n > 0 && outbufsize);
69
70 if (n < 0) {
71 VB2_DEBUG("read() error\n");
72 rv = -1;
73 }
74 }
75 if (waitpid(pid, NULL, 0) < 0) {
76 VB2_DEBUG("waitpid() error\n");
77 rv = -1;
78 }
79 } else { /* Child. */
80 close (p_to_c[STDOUT_FILENO]);
81 close (c_to_p[STDIN_FILENO]);
82 /* Map the stdin to the first pipe (this pipe gets input
83 * from the parent) */
84 if (STDIN_FILENO != p_to_c[STDIN_FILENO]) {
85 if (dup2(p_to_c[STDIN_FILENO], STDIN_FILENO) !=
86 STDIN_FILENO) {
87 VB2_DEBUG("stdin dup2() failed\n");
88 close(p_to_c[0]);
89 return -1;
90 }
91 }
92 /* Map the stdout to the second pipe (this pipe sends back
93 * signer output to the parent) */
94 if (STDOUT_FILENO != c_to_p[STDOUT_FILENO]) {
95 if (dup2(c_to_p[STDOUT_FILENO], STDOUT_FILENO) !=
96 STDOUT_FILENO) {
97 VB2_DEBUG("stdout dup2() failed\n");
98 close(c_to_p[STDOUT_FILENO]);
99 return -1;
100 }
101 }
102 /* External signer is invoked here. */
103 if (execl(external_signer, external_signer, pem_file,
104 (char *) 0) < 0) {
105 VB2_DEBUG("execl() of external signer failed\n");
106 }
107 }
108 return rv;
109 }
110
vb2_external_signature(const uint8_t * data,uint32_t size,const char * key_file,uint32_t key_algorithm,const char * external_signer)111 struct vb2_signature *vb2_external_signature(const uint8_t *data, uint32_t size,
112 const char *key_file,
113 uint32_t key_algorithm,
114 const char *external_signer)
115 {
116 struct vb2_hash hash;
117
118 /* Calculate the digest */
119 if (VB2_SUCCESS != vb2_hash_calculate(false, data, size,
120 vb2_crypto_to_hash(key_algorithm),
121 &hash))
122 return NULL;
123
124 uint32_t digest_info_size = 0;
125 const uint8_t *digest_info = NULL;
126 if (VB2_SUCCESS != vb2_digest_info(hash.algo,
127 &digest_info, &digest_info_size))
128 return NULL;
129
130 int digest_size = vb2_digest_size(hash.algo);
131 uint8_t *signature_digest;
132 uint64_t signature_digest_len = digest_size + digest_info_size;
133
134 int rv;
135
136 /* Prepend the digest info to the digest */
137 signature_digest = calloc(signature_digest_len, 1);
138 if (!signature_digest)
139 return NULL;
140
141 memcpy(signature_digest, digest_info, digest_info_size);
142 memcpy(signature_digest + digest_info_size, hash.raw, digest_size);
143
144 /* Allocate output signature */
145 uint32_t sig_size =
146 vb2_rsa_sig_size(vb2_crypto_to_signature(key_algorithm));
147 struct vb2_signature *sig = vb2_alloc_signature(sig_size, size);
148 if (!sig) {
149 free(signature_digest);
150 return NULL;
151 }
152
153 /* Sign the signature_digest into our output buffer */
154 rv = sign_external(signature_digest_len, /* Input length */
155 signature_digest, /* Input data */
156 vb2_signature_data_mutable(sig), /* Output sig */
157 sig_size, /* Max Output sig size */
158 key_file, /* Key file to use */
159 external_signer); /* External cmd to invoke */
160 free(signature_digest);
161
162 if (-1 == rv) {
163 VB2_DEBUG("RSA_private_encrypt() failed.\n");
164 free(sig);
165 return NULL;
166 }
167
168 /* Return the signature */
169 return sig;
170 }
171