Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: host/lib/host_signature.c

Issue 4194003: Add support for using external signing application and .pem private key files to vbutil_keyblock. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vboot_reference.git
Patch Set: fix read() bug Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « host/lib/host_keyblock.c ('k') | tests/external_rsa_signer.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Host functions for signature generation. 5 * Host functions for signature generation.
6 */ 6 */
7 7
8 /* TODO: change all 'return 0', 'return 1' into meaningful return codes */ 8 /* TODO: change all 'return 0', 'return 1' into meaningful return codes */
9 9
10 #define OPENSSL_NO_SHA 10 #define OPENSSL_NO_SHA
11 #include <openssl/engine.h> 11 #include <openssl/engine.h>
12 #include <openssl/pem.h> 12 #include <openssl/pem.h>
13 #include <openssl/rsa.h> 13 #include <openssl/rsa.h>
14 14
15 #include <stdio.h> 15 #include <stdio.h>
16 #include <stdlib.h> 16 #include <stdlib.h>
17 #include <sys/types.h>
18 #include <sys/wait.h>
17 #include <unistd.h> 19 #include <unistd.h>
18 20
19 #include "cryptolib.h" 21 #include "cryptolib.h"
20 #include "file_keys.h" 22 #include "file_keys.h"
21 #include "utility.h" 23 #include "utility.h"
22 #include "vboot_common.h" 24 #include "vboot_common.h"
23 #include "host_common.h" 25 #include "host_common.h"
24 26
25 27
26 VbSignature* SignatureAlloc(uint64_t sig_size, uint64_t data_size) { 28 VbSignature* SignatureAlloc(uint64_t sig_size, uint64_t data_size) {
27 VbSignature* sig = (VbSignature*)Malloc(sizeof(VbSignature) + sig_size); 29 VbSignature* sig = (VbSignature*)Malloc(sizeof(VbSignature) + sig_size);
28 if (!sig) 30 if (!sig)
29 return NULL; 31 return NULL;
30 32
31 sig->sig_offset = sizeof(VbSignature); 33 sig->sig_offset = sizeof(VbSignature);
32 sig->sig_size = sig_size; 34 sig->sig_size = sig_size;
33 sig->data_size = data_size; 35 sig->data_size = data_size;
34 return sig; 36 return sig;
35 } 37 }
36 38
37 39
38 void SignatureInit(VbSignature* sig, uint8_t* sig_data, 40 void SignatureInit(VbSignature* sig, uint8_t* sig_data,
39 uint64_t sig_size, uint64_t data_size) { 41 uint64_t sig_size, uint64_t data_size) {
40 sig->sig_offset = OffsetOf(sig, sig_data); 42 sig->sig_offset = OffsetOf(sig, sig_data);
41 sig->sig_size = sig_size; 43 sig->sig_size = sig_size;
42 sig->data_size = data_size; 44 sig->data_size = data_size;
43 } 45 }
44 46
45 47
46 int SignatureCopy(VbSignature* dest, const VbSignature* src) { 48 int SignatureCopy(VbSignature* dest, const VbSignature* src) {
47 if (dest->sig_size < src->sig_size) 49 if (dest->sig_size < src->sig_size)
48 return 1; 50 return 1;
49 dest->sig_size = src->sig_size; 51 dest->sig_size = src->sig_size;
(...skipping 20 matching lines...) Expand all
70 sig->sig_offset = sizeof(VbSignature); 72 sig->sig_offset = sizeof(VbSignature);
71 sig->sig_size = SHA512_DIGEST_SIZE; 73 sig->sig_size = SHA512_DIGEST_SIZE;
72 sig->data_size = size; 74 sig->data_size = size;
73 75
74 /* Signature data immediately follows the header */ 76 /* Signature data immediately follows the header */
75 Memcpy(GetSignatureData(sig), header_checksum, SHA512_DIGEST_SIZE); 77 Memcpy(GetSignatureData(sig), header_checksum, SHA512_DIGEST_SIZE);
76 Free(header_checksum); 78 Free(header_checksum);
77 return sig; 79 return sig;
78 } 80 }
79 81
80
81 VbSignature* CalculateSignature(const uint8_t* data, uint64_t size, 82 VbSignature* CalculateSignature(const uint8_t* data, uint64_t size,
82 const VbPrivateKey* key) { 83 const VbPrivateKey* key) {
83 84
84 uint8_t* digest; 85 uint8_t* digest;
85 int digest_size = hash_size_map[key->algorithm]; 86 int digest_size = hash_size_map[key->algorithm];
86 87
87 const uint8_t* digestinfo = hash_digestinfo_map[key->algorithm]; 88 const uint8_t* digestinfo = hash_digestinfo_map[key->algorithm];
88 int digestinfo_size = digestinfo_size_map[key->algorithm]; 89 int digestinfo_size = digestinfo_size_map[key->algorithm];
89 90
90 uint8_t* signature_digest; 91 uint8_t* signature_digest;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 127
127 if (-1 == rv) { 128 if (-1 == rv) {
128 VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n")); 129 VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n"));
129 Free(sig); 130 Free(sig);
130 return NULL; 131 return NULL;
131 } 132 }
132 133
133 /* Return the signature */ 134 /* Return the signature */
134 return sig; 135 return sig;
135 } 136 }
137
138 /* Invoke [external_signer] command with [pem_file] as
139 * an argument, contents of [inbuf] passed redirected to stdin,
140 * and the stdout of the command is put back into [outbuf].
141 * Returns -1 on error, 0 on success.
142 */
143 int InvokeExternalSigner(uint64_t size,
144 const uint8_t* inbuf,
145 uint8_t* outbuf,
146 uint64_t outbufsize,
147 const char* pem_file,
148 const char* external_signer) {
149
150 int rv = 0, n;
151 int p_to_c[2], c_to_p[2]; /* pipe descriptors */
152 pid_t pid;
153
154 VBDEBUG(("Will invoke \"%s %s\" to perform signing.\n"
155 "Input to the signer will be provided on standard in.\n"
156 "Output of the signer will be read from standard out.\n",
157 external_signer, pem_file));
158
159 /* Need two pipes since we want to invoke the external_signer as
160 * a co-process writing to its stdin and reading from its stdout. */
161 if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) {
162 VBDEBUG(("pipe() error\n"));
163 return -1;
164 }
165 if ((pid = fork()) < 0) {
166 VBDEBUG(("fork() error"));
167 return -1;
168 }
169 else if (pid > 0) { /* Parent. */
170 close(p_to_c[STDIN_FILENO]);
171 close(c_to_p[STDOUT_FILENO]);
172
173 /* We provide input to the child process (external signer). */
174 if (write(p_to_c[STDOUT_FILENO], inbuf, size) != size) {
175 VBDEBUG(("write() error while providing input to external signer\n"));
176 rv = -1;
177 } else {
178 close(p_to_c[STDOUT_FILENO]); /* Send EOF to child (signer process). */
179 do {
180 n = read(c_to_p[STDIN_FILENO], outbuf, outbufsize);
181 outbuf += n;
182 outbufsize -= n;
183 } while (n > 0 && outbufsize);
184
185 if (n < 0) {
186 VBDEBUG(("read() error while reading output from external signer\n"));
187 rv = -1;
188 }
189 }
190 if (waitpid(pid, NULL, 0) < 0) {
191 VBDEBUG(("waitpid() error\n"));
192 rv = -1;
193 }
194 } else { /* Child. */
195 close (p_to_c[STDOUT_FILENO]);
196 close (c_to_p[STDIN_FILENO]);
197 /* Map the stdin to the first pipe (this pipe gets input
198 * from the parent) */
199 if (STDIN_FILENO != p_to_c[STDIN_FILENO]) {
200 if (dup2(p_to_c[STDIN_FILENO], STDIN_FILENO) != STDIN_FILENO) {
201 VBDEBUG(("stdin dup2() failed (external signer)\n"));
202 close(p_to_c[0]);
203 return -1;
204 }
205 }
206 /* Map the stdout to the second pipe (this pipe sends back
207 * signer output to the parent) */
208 if (STDOUT_FILENO != c_to_p[STDOUT_FILENO]) {
209 if (dup2(c_to_p[STDOUT_FILENO], STDOUT_FILENO) != STDOUT_FILENO) {
210 VBDEBUG(("stdout dup2() failed (external signer)\n"));
211 close(c_to_p[STDOUT_FILENO]);
212 return -1;
213 }
214 }
215 /* External signer is invoked here. */
216 if (execl(external_signer, external_signer, pem_file, (char *) 0) < 0) {
217 VBDEBUG(("execl() of external signer failed\n"));
218 }
219 }
220 return rv;
221 }
222
223 /* TODO(gauravsh): This could easily be integrated into CalculateSignature()
224 * since the code is almost a mirror - I have kept it as such to avoid changing
225 * the existing interface. */
226 VbSignature* CalculateSignature_external(const uint8_t* data, uint64_t size,
227 const char* key_file,
228 uint64_t key_algorithm,
229 const char* external_signer) {
230 uint8_t* digest;
231 uint64_t digest_size = hash_size_map[key_algorithm];
232
233 const uint8_t* digestinfo = hash_digestinfo_map[key_algorithm];
234 uint64_t digestinfo_size = digestinfo_size_map[key_algorithm];
235
236 uint8_t* signature_digest;
237 uint64_t signature_digest_len = digest_size + digestinfo_size;
238
239 VbSignature* sig;
240 int rv;
241
242 /* Calculate the digest */
243 /* TODO: rename param 3 of DigestBuf to hash_type */
244 digest = DigestBuf(data, size, hash_type_map[key_algorithm]);
245 if (!digest)
246 return NULL;
247
248 /* Prepend the digest info to the digest */
249 signature_digest = Malloc(signature_digest_len);
250 if (!signature_digest) {
251 Free(digest);
252 return NULL;
253 }
254 Memcpy(signature_digest, digestinfo, digestinfo_size);
255 Memcpy(signature_digest + digestinfo_size, digest, digest_size);
256 Free(digest);
257
258 /* Allocate output signature */
259 sig = SignatureAlloc(siglen_map[key_algorithm], size);
260 if (!sig) {
261 Free(signature_digest);
262 return NULL;
263 }
264
265 /* Sign the signature_digest into our output buffer */
266 rv = InvokeExternalSigner(signature_digest_len, /* Input length */
267 signature_digest, /* Input data */
268 GetSignatureData(sig), /* Output sig */
269 (sizeof(VbSignature) + /* Max Output sig size. */
270 siglen_map[key_algorithm]) ,
271 key_file, /* Key file to use */
272 external_signer); /* External cmd to invoke */
273 Free(signature_digest);
274
275 if (-1 == rv) {
276 VBDEBUG(("SignatureBuf(): RSA_private_encrypt() failed.\n"));
277 Free(sig);
278 return NULL;
279 }
280
281 /* Return the signature */
282 return sig;
283 }
OLDNEW
« no previous file with comments | « host/lib/host_keyblock.c ('k') | tests/external_rsa_signer.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698