xref: /aosp_15_r20/external/vboot_reference/host/lib/host_signature.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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