OLD | NEW |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |