Blame view

scripts/extract-cert.c 3.63 KB
1329e8cc6   David Woodhouse   modsign: Extract ...
1
2
  /* Extract X.509 certificate in DER form from PKCS#11 or PEM.
   *
09a77a885   David Woodhouse   modsign: Fix GPL/...
3
4
   * Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved.
   * Copyright © 2015      Intel Corporation.
1329e8cc6   David Woodhouse   modsign: Extract ...
5
6
7
8
9
   *
   * Authors: David Howells <dhowells@redhat.com>
   *          David Woodhouse <dwmw2@infradead.org>
   *
   * This program is free software; you can redistribute it and/or
09a77a885   David Woodhouse   modsign: Fix GPL/...
10
11
12
   * modify it under the terms of the GNU Lesser General Public License
   * as published by the Free Software Foundation; either version 2.1
   * of the licence, or (at your option) any later version.
1329e8cc6   David Woodhouse   modsign: Extract ...
13
14
15
16
17
18
19
   */
  #define _GNU_SOURCE
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdint.h>
  #include <stdbool.h>
  #include <string.h>
1329e8cc6   David Woodhouse   modsign: Extract ...
20
  #include <err.h>
1329e8cc6   David Woodhouse   modsign: Extract ...
21
  #include <openssl/bio.h>
1329e8cc6   David Woodhouse   modsign: Extract ...
22
  #include <openssl/pem.h>
1329e8cc6   David Woodhouse   modsign: Extract ...
23
24
  #include <openssl/err.h>
  #include <openssl/engine.h>
cf9194992   Linus Torvalds   cert host tools: ...
25
26
27
28
29
30
  /*
   * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API.
   *
   * Remove this if/when that API is no longer used
   */
  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1329e8cc6   David Woodhouse   modsign: Extract ...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  #define PKEY_ID_PKCS7 2
  
  static __attribute__((noreturn))
  void format(void)
  {
  	fprintf(stderr,
  		"Usage: scripts/extract-cert <source> <dest>
  ");
  	exit(2);
  }
  
  static void display_openssl_errors(int l)
  {
  	const char *file;
  	char buf[120];
  	int e, line;
  
  	if (ERR_peek_error() == 0)
  		return;
  	fprintf(stderr, "At main.c:%d:
  ", l);
  
  	while ((e = ERR_get_error_line(&file, &line))) {
  		ERR_error_string(e, buf);
  		fprintf(stderr, "- SSL %s: %s:%d
  ", buf, file, line);
  	}
  }
  
  static void drain_openssl_errors(void)
  {
  	const char *file;
  	int line;
  
  	if (ERR_peek_error() == 0)
  		return;
  	while (ERR_get_error_line(&file, &line)) {}
  }
  
  #define ERR(cond, fmt, ...)				\
  	do {						\
  		bool __cond = (cond);			\
  		display_openssl_errors(__LINE__);	\
  		if (__cond) {				\
  			err(1, fmt, ## __VA_ARGS__);	\
  		}					\
  	} while(0)
  
  static const char *key_pass;
84706caae   David Woodhouse   extract-cert: Cop...
80
81
  static BIO *wb;
  static char *cert_dst;
1dbcf46d5   Masahiro Yamada   extract-cert: add...
82
  static int kbuild_verbose;
84706caae   David Woodhouse   extract-cert: Cop...
83
84
85
86
87
88
89
90
91
92
  
  static void write_cert(X509 *x509)
  {
  	char buf[200];
  
  	if (!wb) {
  		wb = BIO_new_file(cert_dst, "wb");
  		ERR(!wb, "%s", cert_dst);
  	}
  	X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf));
7c0d35a33   David Howells   MODSIGN: fix a co...
93
  	ERR(!i2d_X509_bio(wb, x509), "%s", cert_dst);
84706caae   David Woodhouse   extract-cert: Cop...
94
95
96
97
  	if (kbuild_verbose)
  		fprintf(stderr, "Extracted cert: %s
  ", buf);
  }
1329e8cc6   David Woodhouse   modsign: Extract ...
98
99
100
  
  int main(int argc, char **argv)
  {
84706caae   David Woodhouse   extract-cert: Cop...
101
  	char *cert_src;
1329e8cc6   David Woodhouse   modsign: Extract ...
102
103
104
105
  
  	OpenSSL_add_all_algorithms();
  	ERR_load_crypto_strings();
  	ERR_clear_error();
84706caae   David Woodhouse   extract-cert: Cop...
106
  	kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0");
1329e8cc6   David Woodhouse   modsign: Extract ...
107
108
109
110
111
112
113
          key_pass = getenv("KBUILD_SIGN_PIN");
  
  	if (argc != 3)
  		format();
  
  	cert_src = argv[1];
  	cert_dst = argv[2];
84706caae   David Woodhouse   extract-cert: Cop...
114
115
116
117
118
119
120
  	if (!cert_src[0]) {
  		/* Invoked with no input; create empty file */
  		FILE *f = fopen(cert_dst, "wb");
  		ERR(!f, "%s", cert_dst);
  		fclose(f);
  		exit(0);
  	} else if (!strncmp(cert_src, "pkcs11:", 7)) {
1329e8cc6   David Woodhouse   modsign: Extract ...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  		ENGINE *e;
  		struct {
  			const char *cert_id;
  			X509 *cert;
  		} parms;
  
  		parms.cert_id = cert_src;
  		parms.cert = NULL;
  
  		ENGINE_load_builtin_engines();
  		drain_openssl_errors();
  		e = ENGINE_by_id("pkcs11");
  		ERR(!e, "Load PKCS#11 ENGINE");
  		if (ENGINE_init(e))
  			drain_openssl_errors();
  		else
  			ERR(1, "ENGINE_init");
  		if (key_pass)
  			ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
  		ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);
  		ERR(!parms.cert, "Get X.509 from PKCS#11");
84706caae   David Woodhouse   extract-cert: Cop...
142
  		write_cert(parms.cert);
1329e8cc6   David Woodhouse   modsign: Extract ...
143
  	} else {
84706caae   David Woodhouse   extract-cert: Cop...
144
145
  		BIO *b;
  		X509 *x509;
1329e8cc6   David Woodhouse   modsign: Extract ...
146
147
  		b = BIO_new_file(cert_src, "rb");
  		ERR(!b, "%s", cert_src);
84706caae   David Woodhouse   extract-cert: Cop...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  
  		while (1) {
  			x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
  			if (wb && !x509) {
  				unsigned long err = ERR_peek_last_error();
  				if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
  				    ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
  					ERR_clear_error();
  					break;
  				}
  			}
  			ERR(!x509, "%s", cert_src);
  			write_cert(x509);
  		}
1329e8cc6   David Woodhouse   modsign: Extract ...
162
  	}
84706caae   David Woodhouse   extract-cert: Cop...
163
  	BIO_free(wb);
1329e8cc6   David Woodhouse   modsign: Extract ...
164
165
166
  
  	return 0;
  }