1e595e65bSEdward Tomasz Napierala /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31aa6f9aeSEdward Tomasz Napierala *
4e595e65bSEdward Tomasz Napierala * Copyright (c) 2014 The FreeBSD Foundation
5e595e65bSEdward Tomasz Napierala *
6e595e65bSEdward Tomasz Napierala * This software was developed by Edward Tomasz Napierala under sponsorship
7e595e65bSEdward Tomasz Napierala * from the FreeBSD Foundation.
8e595e65bSEdward Tomasz Napierala *
9e595e65bSEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without
10e595e65bSEdward Tomasz Napierala * modification, are permitted provided that the following conditions
11e595e65bSEdward Tomasz Napierala * are met:
12e595e65bSEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright
13e595e65bSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer.
14e595e65bSEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright
15e595e65bSEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the
16e595e65bSEdward Tomasz Napierala * documentation and/or other materials provided with the distribution.
17e595e65bSEdward Tomasz Napierala *
18e595e65bSEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19e595e65bSEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20e595e65bSEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21e595e65bSEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22e595e65bSEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23e595e65bSEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24e595e65bSEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25e595e65bSEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26e595e65bSEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27e595e65bSEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28e595e65bSEdward Tomasz Napierala * SUCH DAMAGE.
29e595e65bSEdward Tomasz Napierala *
30e595e65bSEdward Tomasz Napierala */
31e595e65bSEdward Tomasz Napierala
32e595e65bSEdward Tomasz Napierala #include <sys/cdefs.h>
33e595e65bSEdward Tomasz Napierala #include <sys/wait.h>
34e595e65bSEdward Tomasz Napierala #include <assert.h>
35e595e65bSEdward Tomasz Napierala #include <err.h>
36e595e65bSEdward Tomasz Napierala #include <errno.h>
37e595e65bSEdward Tomasz Napierala #include <stdio.h>
38e595e65bSEdward Tomasz Napierala #include <string.h>
39e595e65bSEdward Tomasz Napierala #include <unistd.h>
40e595e65bSEdward Tomasz Napierala
41e595e65bSEdward Tomasz Napierala #include <openssl/conf.h>
42e595e65bSEdward Tomasz Napierala #include <openssl/evp.h>
43e595e65bSEdward Tomasz Napierala #include <openssl/err.h>
44e595e65bSEdward Tomasz Napierala #include <openssl/pem.h>
45e595e65bSEdward Tomasz Napierala #include <openssl/pkcs7.h>
46e595e65bSEdward Tomasz Napierala
47e595e65bSEdward Tomasz Napierala #include "uefisign.h"
48e595e65bSEdward Tomasz Napierala #include "magic.h"
49e595e65bSEdward Tomasz Napierala
50e595e65bSEdward Tomasz Napierala static void
usage(void)51e595e65bSEdward Tomasz Napierala usage(void)
52e595e65bSEdward Tomasz Napierala {
53e595e65bSEdward Tomasz Napierala
54e595e65bSEdward Tomasz Napierala fprintf(stderr, "usage: uefisign -c cert -k key -o outfile [-v] file\n"
55e595e65bSEdward Tomasz Napierala " uefisign -V [-c cert] [-v] file\n");
56e595e65bSEdward Tomasz Napierala exit(1);
57e595e65bSEdward Tomasz Napierala }
58e595e65bSEdward Tomasz Napierala
59e595e65bSEdward Tomasz Napierala static char *
checked_strdup(const char * s)60e595e65bSEdward Tomasz Napierala checked_strdup(const char *s)
61e595e65bSEdward Tomasz Napierala {
62e595e65bSEdward Tomasz Napierala char *c;
63e595e65bSEdward Tomasz Napierala
64e595e65bSEdward Tomasz Napierala c = strdup(s);
65e595e65bSEdward Tomasz Napierala if (c == NULL)
66e595e65bSEdward Tomasz Napierala err(1, "strdup");
67e595e65bSEdward Tomasz Napierala return (c);
68e595e65bSEdward Tomasz Napierala }
69e595e65bSEdward Tomasz Napierala
70e595e65bSEdward Tomasz Napierala FILE *
checked_fopen(const char * path,const char * mode)71e595e65bSEdward Tomasz Napierala checked_fopen(const char *path, const char *mode)
72e595e65bSEdward Tomasz Napierala {
73e595e65bSEdward Tomasz Napierala FILE *fp;
74e595e65bSEdward Tomasz Napierala
75e595e65bSEdward Tomasz Napierala assert(path != NULL);
76e595e65bSEdward Tomasz Napierala
77e595e65bSEdward Tomasz Napierala fp = fopen(path, mode);
78e595e65bSEdward Tomasz Napierala if (fp == NULL)
79e595e65bSEdward Tomasz Napierala err(1, "%s", path);
80e595e65bSEdward Tomasz Napierala return (fp);
81e595e65bSEdward Tomasz Napierala }
82e595e65bSEdward Tomasz Napierala
83e595e65bSEdward Tomasz Napierala void
send_chunk(const void * buf,size_t len,int pipefd)84e595e65bSEdward Tomasz Napierala send_chunk(const void *buf, size_t len, int pipefd)
85e595e65bSEdward Tomasz Napierala {
86e595e65bSEdward Tomasz Napierala ssize_t ret;
87e595e65bSEdward Tomasz Napierala
88e595e65bSEdward Tomasz Napierala ret = write(pipefd, &len, sizeof(len));
89e595e65bSEdward Tomasz Napierala if (ret != sizeof(len))
90e595e65bSEdward Tomasz Napierala err(1, "write");
91e595e65bSEdward Tomasz Napierala ret = write(pipefd, buf, len);
92e595e65bSEdward Tomasz Napierala if (ret != (ssize_t)len)
93e595e65bSEdward Tomasz Napierala err(1, "write");
94e595e65bSEdward Tomasz Napierala }
95e595e65bSEdward Tomasz Napierala
96e595e65bSEdward Tomasz Napierala void
receive_chunk(void ** bufp,size_t * lenp,int pipefd)97e595e65bSEdward Tomasz Napierala receive_chunk(void **bufp, size_t *lenp, int pipefd)
98e595e65bSEdward Tomasz Napierala {
99e595e65bSEdward Tomasz Napierala ssize_t ret;
100e595e65bSEdward Tomasz Napierala size_t len;
101e595e65bSEdward Tomasz Napierala void *buf;
102e595e65bSEdward Tomasz Napierala
103e595e65bSEdward Tomasz Napierala ret = read(pipefd, &len, sizeof(len));
104e595e65bSEdward Tomasz Napierala if (ret != sizeof(len))
105e595e65bSEdward Tomasz Napierala err(1, "read");
106e595e65bSEdward Tomasz Napierala
107e595e65bSEdward Tomasz Napierala buf = calloc(1, len);
108e595e65bSEdward Tomasz Napierala if (buf == NULL)
109e595e65bSEdward Tomasz Napierala err(1, "calloc");
110e595e65bSEdward Tomasz Napierala
111e595e65bSEdward Tomasz Napierala ret = read(pipefd, buf, len);
112e595e65bSEdward Tomasz Napierala if (ret != (ssize_t)len)
113e595e65bSEdward Tomasz Napierala err(1, "read");
114e595e65bSEdward Tomasz Napierala
115e595e65bSEdward Tomasz Napierala *bufp = buf;
116e595e65bSEdward Tomasz Napierala *lenp = len;
117e595e65bSEdward Tomasz Napierala }
118e595e65bSEdward Tomasz Napierala
119e595e65bSEdward Tomasz Napierala static char *
bin2hex(const char * bin,size_t bin_len)120e595e65bSEdward Tomasz Napierala bin2hex(const char *bin, size_t bin_len)
121e595e65bSEdward Tomasz Napierala {
122e595e65bSEdward Tomasz Napierala unsigned char *hex, *tmp, ch;
123e595e65bSEdward Tomasz Napierala size_t hex_len;
124e595e65bSEdward Tomasz Napierala size_t i;
125e595e65bSEdward Tomasz Napierala
126e595e65bSEdward Tomasz Napierala hex_len = bin_len * 2 + 1; /* +1 for '\0'. */
127e595e65bSEdward Tomasz Napierala hex = malloc(hex_len);
128e595e65bSEdward Tomasz Napierala if (hex == NULL)
129e595e65bSEdward Tomasz Napierala err(1, "malloc");
130e595e65bSEdward Tomasz Napierala
131e595e65bSEdward Tomasz Napierala tmp = hex;
132e595e65bSEdward Tomasz Napierala for (i = 0; i < bin_len; i++) {
133e595e65bSEdward Tomasz Napierala ch = bin[i];
134e595e65bSEdward Tomasz Napierala tmp += sprintf(tmp, "%02x", ch);
135e595e65bSEdward Tomasz Napierala }
136e595e65bSEdward Tomasz Napierala
137e595e65bSEdward Tomasz Napierala return (hex);
138e595e65bSEdward Tomasz Napierala }
139e595e65bSEdward Tomasz Napierala
140e595e65bSEdward Tomasz Napierala /*
141e595e65bSEdward Tomasz Napierala * We need to replace a standard chunk of PKCS7 signature with one mandated
142e595e65bSEdward Tomasz Napierala * by Authenticode. Problem is, replacing it just like that and then calling
143e595e65bSEdward Tomasz Napierala * PKCS7_final() would make OpenSSL segfault somewhere in PKCS7_dataFinal().
144e595e65bSEdward Tomasz Napierala * So, instead, we call PKCS7_dataInit(), then put our Authenticode-specific
145e595e65bSEdward Tomasz Napierala * data into BIO it returned, then call PKCS7_dataFinal() - which now somehow
146e595e65bSEdward Tomasz Napierala * does not panic - and _then_ we replace it in the signature. This technique
147e595e65bSEdward Tomasz Napierala * was used in sbsigntool by Jeremy Kerr, and might have originated in
148e595e65bSEdward Tomasz Napierala * osslsigncode.
149e595e65bSEdward Tomasz Napierala */
150e595e65bSEdward Tomasz Napierala static void
magic(PKCS7 * pkcs7,const char * digest,size_t digest_len)151e595e65bSEdward Tomasz Napierala magic(PKCS7 *pkcs7, const char *digest, size_t digest_len)
152e595e65bSEdward Tomasz Napierala {
153e595e65bSEdward Tomasz Napierala BIO *bio, *t_bio;
154e595e65bSEdward Tomasz Napierala ASN1_TYPE *t;
155e595e65bSEdward Tomasz Napierala ASN1_STRING *s;
156e595e65bSEdward Tomasz Napierala CONF *cnf;
157e595e65bSEdward Tomasz Napierala unsigned char *buf, *tmp;
158e595e65bSEdward Tomasz Napierala char *digest_hex, *magic_conf, *str;
159e595e65bSEdward Tomasz Napierala int len, nid, ok;
160e595e65bSEdward Tomasz Napierala
161e595e65bSEdward Tomasz Napierala digest_hex = bin2hex(digest, digest_len);
162e595e65bSEdward Tomasz Napierala
163e595e65bSEdward Tomasz Napierala /*
164e595e65bSEdward Tomasz Napierala * Construct the SpcIndirectDataContent chunk.
165e595e65bSEdward Tomasz Napierala */
166e595e65bSEdward Tomasz Napierala nid = OBJ_create("1.3.6.1.4.1.311.2.1.4", NULL, NULL);
167e595e65bSEdward Tomasz Napierala
168e595e65bSEdward Tomasz Napierala asprintf(&magic_conf, magic_fmt, digest_hex);
169e595e65bSEdward Tomasz Napierala if (magic_conf == NULL)
170e595e65bSEdward Tomasz Napierala err(1, "asprintf");
171e595e65bSEdward Tomasz Napierala
172e595e65bSEdward Tomasz Napierala bio = BIO_new_mem_buf((void *)magic_conf, -1);
173e595e65bSEdward Tomasz Napierala if (bio == NULL) {
174e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
175e595e65bSEdward Tomasz Napierala errx(1, "BIO_new_mem_buf(3) failed");
176e595e65bSEdward Tomasz Napierala }
177e595e65bSEdward Tomasz Napierala
178e595e65bSEdward Tomasz Napierala cnf = NCONF_new(NULL);
179e595e65bSEdward Tomasz Napierala if (cnf == NULL) {
180e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
181e595e65bSEdward Tomasz Napierala errx(1, "NCONF_new(3) failed");
182e595e65bSEdward Tomasz Napierala }
183e595e65bSEdward Tomasz Napierala
184e595e65bSEdward Tomasz Napierala ok = NCONF_load_bio(cnf, bio, NULL);
185e595e65bSEdward Tomasz Napierala if (ok == 0) {
186e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
187e595e65bSEdward Tomasz Napierala errx(1, "NCONF_load_bio(3) failed");
188e595e65bSEdward Tomasz Napierala }
189e595e65bSEdward Tomasz Napierala
190e595e65bSEdward Tomasz Napierala str = NCONF_get_string(cnf, "default", "asn1");
191e595e65bSEdward Tomasz Napierala if (str == NULL) {
192e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
193e595e65bSEdward Tomasz Napierala errx(1, "NCONF_get_string(3) failed");
194e595e65bSEdward Tomasz Napierala }
195e595e65bSEdward Tomasz Napierala
196e595e65bSEdward Tomasz Napierala t = ASN1_generate_nconf(str, cnf);
197e595e65bSEdward Tomasz Napierala if (t == NULL) {
198e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
199e595e65bSEdward Tomasz Napierala errx(1, "ASN1_generate_nconf(3) failed");
200e595e65bSEdward Tomasz Napierala }
201e595e65bSEdward Tomasz Napierala
202e595e65bSEdward Tomasz Napierala /*
203e595e65bSEdward Tomasz Napierala * We now have our proprietary piece of ASN.1. Let's do
204e595e65bSEdward Tomasz Napierala * the actual signing.
205e595e65bSEdward Tomasz Napierala */
206e595e65bSEdward Tomasz Napierala len = i2d_ASN1_TYPE(t, NULL);
207e595e65bSEdward Tomasz Napierala tmp = buf = calloc(1, len);
208e595e65bSEdward Tomasz Napierala if (tmp == NULL)
209e595e65bSEdward Tomasz Napierala err(1, "calloc");
210e595e65bSEdward Tomasz Napierala i2d_ASN1_TYPE(t, &tmp);
211e595e65bSEdward Tomasz Napierala
212e595e65bSEdward Tomasz Napierala /*
213e595e65bSEdward Tomasz Napierala * We now have contents of 't' stuffed into memory buffer 'buf'.
214e595e65bSEdward Tomasz Napierala */
215e595e65bSEdward Tomasz Napierala tmp = NULL;
216e595e65bSEdward Tomasz Napierala t = NULL;
217e595e65bSEdward Tomasz Napierala
218e595e65bSEdward Tomasz Napierala t_bio = PKCS7_dataInit(pkcs7, NULL);
219e595e65bSEdward Tomasz Napierala if (t_bio == NULL) {
220e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
221e595e65bSEdward Tomasz Napierala errx(1, "PKCS7_dataInit(3) failed");
222e595e65bSEdward Tomasz Napierala }
223e595e65bSEdward Tomasz Napierala
224e595e65bSEdward Tomasz Napierala BIO_write(t_bio, buf + 2, len - 2);
225e595e65bSEdward Tomasz Napierala
226e595e65bSEdward Tomasz Napierala ok = PKCS7_dataFinal(pkcs7, t_bio);
227e595e65bSEdward Tomasz Napierala if (ok == 0) {
228e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
229e595e65bSEdward Tomasz Napierala errx(1, "PKCS7_dataFinal(3) failed");
230e595e65bSEdward Tomasz Napierala }
231e595e65bSEdward Tomasz Napierala
232e595e65bSEdward Tomasz Napierala t = ASN1_TYPE_new();
233e595e65bSEdward Tomasz Napierala s = ASN1_STRING_new();
234e595e65bSEdward Tomasz Napierala ASN1_STRING_set(s, buf, len);
235e595e65bSEdward Tomasz Napierala ASN1_TYPE_set(t, V_ASN1_SEQUENCE, s);
236e595e65bSEdward Tomasz Napierala
237e595e65bSEdward Tomasz Napierala PKCS7_set0_type_other(pkcs7->d.sign->contents, nid, t);
238e595e65bSEdward Tomasz Napierala }
239e595e65bSEdward Tomasz Napierala
240e595e65bSEdward Tomasz Napierala static void
sign(X509 * cert,EVP_PKEY * key,int pipefd)241e595e65bSEdward Tomasz Napierala sign(X509 *cert, EVP_PKEY *key, int pipefd)
242e595e65bSEdward Tomasz Napierala {
243e595e65bSEdward Tomasz Napierala PKCS7 *pkcs7;
244e595e65bSEdward Tomasz Napierala BIO *bio, *out;
245e595e65bSEdward Tomasz Napierala const EVP_MD *md;
246e595e65bSEdward Tomasz Napierala PKCS7_SIGNER_INFO *info;
247e595e65bSEdward Tomasz Napierala void *digest, *signature;
248e595e65bSEdward Tomasz Napierala size_t digest_len, signature_len;
249e595e65bSEdward Tomasz Napierala int ok;
250e595e65bSEdward Tomasz Napierala
251e595e65bSEdward Tomasz Napierala assert(cert != NULL);
252e595e65bSEdward Tomasz Napierala assert(key != NULL);
253e595e65bSEdward Tomasz Napierala
254e595e65bSEdward Tomasz Napierala receive_chunk(&digest, &digest_len, pipefd);
255e595e65bSEdward Tomasz Napierala
256e595e65bSEdward Tomasz Napierala bio = BIO_new_mem_buf(digest, digest_len);
257e595e65bSEdward Tomasz Napierala if (bio == NULL) {
258e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
259e595e65bSEdward Tomasz Napierala errx(1, "BIO_new_mem_buf(3) failed");
260e595e65bSEdward Tomasz Napierala }
261e595e65bSEdward Tomasz Napierala
262e595e65bSEdward Tomasz Napierala pkcs7 = PKCS7_sign(NULL, NULL, NULL, bio, PKCS7_BINARY | PKCS7_PARTIAL);
263e595e65bSEdward Tomasz Napierala if (pkcs7 == NULL) {
264e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
265e595e65bSEdward Tomasz Napierala errx(1, "PKCS7_sign(3) failed");
266e595e65bSEdward Tomasz Napierala }
267e595e65bSEdward Tomasz Napierala
268e595e65bSEdward Tomasz Napierala md = EVP_get_digestbyname(DIGEST);
269e595e65bSEdward Tomasz Napierala if (md == NULL) {
270e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
271e595e65bSEdward Tomasz Napierala errx(1, "EVP_get_digestbyname(\"%s\") failed", DIGEST);
272e595e65bSEdward Tomasz Napierala }
273e595e65bSEdward Tomasz Napierala
274e595e65bSEdward Tomasz Napierala info = PKCS7_sign_add_signer(pkcs7, cert, key, md, 0);
275e595e65bSEdward Tomasz Napierala if (info == NULL) {
276e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
277e595e65bSEdward Tomasz Napierala errx(1, "PKCS7_sign_add_signer(3) failed");
278e595e65bSEdward Tomasz Napierala }
279e595e65bSEdward Tomasz Napierala
280e595e65bSEdward Tomasz Napierala /*
281e595e65bSEdward Tomasz Napierala * XXX: All the signed binaries seem to have this, but where is it
282e595e65bSEdward Tomasz Napierala * described in the spec?
283e595e65bSEdward Tomasz Napierala */
284e595e65bSEdward Tomasz Napierala PKCS7_add_signed_attribute(info, NID_pkcs9_contentType,
285e595e65bSEdward Tomasz Napierala V_ASN1_OBJECT, OBJ_txt2obj("1.3.6.1.4.1.311.2.1.4", 1));
286e595e65bSEdward Tomasz Napierala
287e595e65bSEdward Tomasz Napierala magic(pkcs7, digest, digest_len);
288e595e65bSEdward Tomasz Napierala
289e595e65bSEdward Tomasz Napierala #if 0
290e595e65bSEdward Tomasz Napierala out = BIO_new(BIO_s_file());
291e595e65bSEdward Tomasz Napierala BIO_set_fp(out, stdout, BIO_NOCLOSE);
292e595e65bSEdward Tomasz Napierala PKCS7_print_ctx(out, pkcs7, 0, NULL);
293e595e65bSEdward Tomasz Napierala
294e595e65bSEdward Tomasz Napierala i2d_PKCS7_bio(out, pkcs7);
295e595e65bSEdward Tomasz Napierala #endif
296e595e65bSEdward Tomasz Napierala
297e595e65bSEdward Tomasz Napierala out = BIO_new(BIO_s_mem());
298e595e65bSEdward Tomasz Napierala if (out == NULL) {
299e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
300e595e65bSEdward Tomasz Napierala errx(1, "BIO_new(3) failed");
301e595e65bSEdward Tomasz Napierala }
302e595e65bSEdward Tomasz Napierala
303e595e65bSEdward Tomasz Napierala ok = i2d_PKCS7_bio(out, pkcs7);
304e595e65bSEdward Tomasz Napierala if (ok == 0) {
305e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
306e595e65bSEdward Tomasz Napierala errx(1, "i2d_PKCS7_bio(3) failed");
307e595e65bSEdward Tomasz Napierala }
308e595e65bSEdward Tomasz Napierala
309e595e65bSEdward Tomasz Napierala signature_len = BIO_get_mem_data(out, &signature);
310e595e65bSEdward Tomasz Napierala if (signature_len <= 0) {
311e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
312e595e65bSEdward Tomasz Napierala errx(1, "BIO_get_mem_data(3) failed");
313e595e65bSEdward Tomasz Napierala }
314e595e65bSEdward Tomasz Napierala
315e595e65bSEdward Tomasz Napierala (void)BIO_set_close(out, BIO_NOCLOSE);
316e595e65bSEdward Tomasz Napierala BIO_free(out);
317e595e65bSEdward Tomasz Napierala
318e595e65bSEdward Tomasz Napierala send_chunk(signature, signature_len, pipefd);
319e595e65bSEdward Tomasz Napierala }
320e595e65bSEdward Tomasz Napierala
321e595e65bSEdward Tomasz Napierala static int
wait_for_child(pid_t pid)322e595e65bSEdward Tomasz Napierala wait_for_child(pid_t pid)
323e595e65bSEdward Tomasz Napierala {
324e595e65bSEdward Tomasz Napierala int status;
325e595e65bSEdward Tomasz Napierala
326e595e65bSEdward Tomasz Napierala pid = waitpid(pid, &status, 0);
327e595e65bSEdward Tomasz Napierala if (pid == -1)
328e595e65bSEdward Tomasz Napierala err(1, "waitpid");
329e595e65bSEdward Tomasz Napierala
330e595e65bSEdward Tomasz Napierala return (WEXITSTATUS(status));
331e595e65bSEdward Tomasz Napierala }
332e595e65bSEdward Tomasz Napierala
333e595e65bSEdward Tomasz Napierala int
main(int argc,char ** argv)334e595e65bSEdward Tomasz Napierala main(int argc, char **argv)
335e595e65bSEdward Tomasz Napierala {
336e595e65bSEdward Tomasz Napierala int ch, error;
337e595e65bSEdward Tomasz Napierala bool Vflag = false, vflag = false;
338e595e65bSEdward Tomasz Napierala const char *certpath = NULL, *keypath = NULL, *outpath = NULL, *inpath = NULL;
339e595e65bSEdward Tomasz Napierala FILE *certfp = NULL, *keyfp = NULL;
340e595e65bSEdward Tomasz Napierala X509 *cert = NULL;
341e595e65bSEdward Tomasz Napierala EVP_PKEY *key = NULL;
342e595e65bSEdward Tomasz Napierala pid_t pid;
343e595e65bSEdward Tomasz Napierala int pipefds[2];
344e595e65bSEdward Tomasz Napierala
345e595e65bSEdward Tomasz Napierala while ((ch = getopt(argc, argv, "Vc:k:o:v")) != -1) {
346e595e65bSEdward Tomasz Napierala switch (ch) {
347e595e65bSEdward Tomasz Napierala case 'V':
348e595e65bSEdward Tomasz Napierala Vflag = true;
349e595e65bSEdward Tomasz Napierala break;
350e595e65bSEdward Tomasz Napierala case 'c':
3516234a0bfSXin LI if (certpath == NULL)
352e595e65bSEdward Tomasz Napierala certpath = checked_strdup(optarg);
3536234a0bfSXin LI else
3546234a0bfSXin LI err(1, "-c can only be specified once");
355e595e65bSEdward Tomasz Napierala break;
356e595e65bSEdward Tomasz Napierala case 'k':
3576234a0bfSXin LI if (keypath == NULL)
358e595e65bSEdward Tomasz Napierala keypath = checked_strdup(optarg);
3596234a0bfSXin LI else
3606234a0bfSXin LI err(1, "-k can only be specified once");
361e595e65bSEdward Tomasz Napierala break;
362e595e65bSEdward Tomasz Napierala case 'o':
3636234a0bfSXin LI if (outpath == NULL)
364e595e65bSEdward Tomasz Napierala outpath = checked_strdup(optarg);
3656234a0bfSXin LI else
3666234a0bfSXin LI err(1, "-o can only be specified once");
367e595e65bSEdward Tomasz Napierala break;
368e595e65bSEdward Tomasz Napierala case 'v':
369e595e65bSEdward Tomasz Napierala vflag = true;
370e595e65bSEdward Tomasz Napierala break;
371e595e65bSEdward Tomasz Napierala default:
372e595e65bSEdward Tomasz Napierala usage();
373e595e65bSEdward Tomasz Napierala }
374e595e65bSEdward Tomasz Napierala }
375e595e65bSEdward Tomasz Napierala
376e595e65bSEdward Tomasz Napierala argc -= optind;
377e595e65bSEdward Tomasz Napierala argv += optind;
378e595e65bSEdward Tomasz Napierala if (argc != 1)
379e595e65bSEdward Tomasz Napierala usage();
380e595e65bSEdward Tomasz Napierala
381e595e65bSEdward Tomasz Napierala if (Vflag) {
382e595e65bSEdward Tomasz Napierala if (certpath != NULL)
383e595e65bSEdward Tomasz Napierala errx(1, "-V and -c are mutually exclusive");
384e595e65bSEdward Tomasz Napierala if (keypath != NULL)
385e595e65bSEdward Tomasz Napierala errx(1, "-V and -k are mutually exclusive");
386e595e65bSEdward Tomasz Napierala if (outpath != NULL)
387e595e65bSEdward Tomasz Napierala errx(1, "-V and -o are mutually exclusive");
388e595e65bSEdward Tomasz Napierala } else {
389e595e65bSEdward Tomasz Napierala if (certpath == NULL)
390e595e65bSEdward Tomasz Napierala errx(1, "-c option is mandatory");
391e595e65bSEdward Tomasz Napierala if (keypath == NULL)
392e595e65bSEdward Tomasz Napierala errx(1, "-k option is mandatory");
393e595e65bSEdward Tomasz Napierala if (outpath == NULL)
394e595e65bSEdward Tomasz Napierala errx(1, "-o option is mandatory");
395e595e65bSEdward Tomasz Napierala }
396e595e65bSEdward Tomasz Napierala
397e595e65bSEdward Tomasz Napierala inpath = argv[0];
398e595e65bSEdward Tomasz Napierala
3996bd321e6SJung-uk Kim OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG |
4006bd321e6SJung-uk Kim OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
4016bd321e6SJung-uk Kim OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
402e595e65bSEdward Tomasz Napierala
403e595e65bSEdward Tomasz Napierala error = pipe(pipefds);
404e595e65bSEdward Tomasz Napierala if (error != 0)
405e595e65bSEdward Tomasz Napierala err(1, "pipe");
406e595e65bSEdward Tomasz Napierala
407e595e65bSEdward Tomasz Napierala pid = fork();
408e595e65bSEdward Tomasz Napierala if (pid < 0)
409e595e65bSEdward Tomasz Napierala err(1, "fork");
410e595e65bSEdward Tomasz Napierala
4119e6158d2SEric van Gyzen if (pid == 0) {
4129e6158d2SEric van Gyzen close(pipefds[0]);
4136234a0bfSXin LI exit(child(inpath, outpath, pipefds[1], Vflag, vflag));
4149e6158d2SEric van Gyzen }
4159e6158d2SEric van Gyzen
4169e6158d2SEric van Gyzen close(pipefds[1]);
417e595e65bSEdward Tomasz Napierala
418e595e65bSEdward Tomasz Napierala if (!Vflag) {
419e595e65bSEdward Tomasz Napierala certfp = checked_fopen(certpath, "r");
420e595e65bSEdward Tomasz Napierala cert = PEM_read_X509(certfp, NULL, NULL, NULL);
421e595e65bSEdward Tomasz Napierala if (cert == NULL) {
422e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
423e595e65bSEdward Tomasz Napierala errx(1, "failed to load certificate from %s", certpath);
424e595e65bSEdward Tomasz Napierala }
425e595e65bSEdward Tomasz Napierala
426e595e65bSEdward Tomasz Napierala keyfp = checked_fopen(keypath, "r");
427e595e65bSEdward Tomasz Napierala key = PEM_read_PrivateKey(keyfp, NULL, NULL, NULL);
428e595e65bSEdward Tomasz Napierala if (key == NULL) {
429e595e65bSEdward Tomasz Napierala ERR_print_errors_fp(stderr);
430e595e65bSEdward Tomasz Napierala errx(1, "failed to load private key from %s", keypath);
431e595e65bSEdward Tomasz Napierala }
432e595e65bSEdward Tomasz Napierala
433e595e65bSEdward Tomasz Napierala sign(cert, key, pipefds[0]);
434e595e65bSEdward Tomasz Napierala }
435e595e65bSEdward Tomasz Napierala
4366234a0bfSXin LI exit(wait_for_child(pid));
437e595e65bSEdward Tomasz Napierala }
438