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