Blame view

scripts/extract-cert.c 3.61 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  #include <openssl/err.h>
  #include <openssl/engine.h>
  
  #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);
  	}
  }
2841a4316   Matthias Maennich   ANDROID: extract-...
54
  #ifndef OPENSSL_IS_BORINGSSL
1329e8cc6   David Woodhouse   modsign: Extract ...
55
56
57
58
59
60
61
62
63
  static void drain_openssl_errors(void)
  {
  	const char *file;
  	int line;
  
  	if (ERR_peek_error() == 0)
  		return;
  	while (ERR_get_error_line(&file, &line)) {}
  }
2841a4316   Matthias Maennich   ANDROID: extract-...
64
  #endif
1329e8cc6   David Woodhouse   modsign: Extract ...
65
66
67
68
69
70
71
72
73
74
75
  
  #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...
76
77
  static BIO *wb;
  static char *cert_dst;
1dbcf46d5   Masahiro Yamada   extract-cert: add...
78
  static int kbuild_verbose;
84706caae   David Woodhouse   extract-cert: Cop...
79
80
81
82
83
84
85
86
87
88
  
  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...
89
  	ERR(!i2d_X509_bio(wb, x509), "%s", cert_dst);
84706caae   David Woodhouse   extract-cert: Cop...
90
91
92
93
  	if (kbuild_verbose)
  		fprintf(stderr, "Extracted cert: %s
  ", buf);
  }
1329e8cc6   David Woodhouse   modsign: Extract ...
94
95
96
  
  int main(int argc, char **argv)
  {
84706caae   David Woodhouse   extract-cert: Cop...
97
  	char *cert_src;
1329e8cc6   David Woodhouse   modsign: Extract ...
98
99
100
101
  
  	OpenSSL_add_all_algorithms();
  	ERR_load_crypto_strings();
  	ERR_clear_error();
84706caae   David Woodhouse   extract-cert: Cop...
102
  	kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0");
1329e8cc6   David Woodhouse   modsign: Extract ...
103
104
105
106
107
108
109
          key_pass = getenv("KBUILD_SIGN_PIN");
  
  	if (argc != 3)
  		format();
  
  	cert_src = argv[1];
  	cert_dst = argv[2];
84706caae   David Woodhouse   extract-cert: Cop...
110
111
112
113
114
115
116
  	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)) {
2841a4316   Matthias Maennich   ANDROID: extract-...
117
118
119
120
  #ifdef OPENSSL_IS_BORINGSSL
  		ERR(1, "BoringSSL does not support extracting from PKCS#11");
  		exit(1);
  #else
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);
2841a4316   Matthias Maennich   ANDROID: extract-...
143
  #endif
1329e8cc6   David Woodhouse   modsign: Extract ...
144
  	} else {
84706caae   David Woodhouse   extract-cert: Cop...
145
146
  		BIO *b;
  		X509 *x509;
1329e8cc6   David Woodhouse   modsign: Extract ...
147
148
  		b = BIO_new_file(cert_src, "rb");
  		ERR(!b, "%s", cert_src);
84706caae   David Woodhouse   extract-cert: Cop...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  
  		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 ...
163
  	}
84706caae   David Woodhouse   extract-cert: Cop...
164
  	BIO_free(wb);
1329e8cc6   David Woodhouse   modsign: Extract ...
165
166
167
  
  	return 0;
  }