Blame view

scripts/extract-cert.c 3.46 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  #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);
  	}
  }
  
  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...
75
76
77
78
79
80
81
82
83
84
85
86
87
  static BIO *wb;
  static char *cert_dst;
  int kbuild_verbose;
  
  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...
88
  	ERR(!i2d_X509_bio(wb, x509), "%s", cert_dst);
84706caae   David Woodhouse   extract-cert: Cop...
89
90
91
92
  	if (kbuild_verbose)
  		fprintf(stderr, "Extracted cert: %s
  ", buf);
  }
1329e8cc6   David Woodhouse   modsign: Extract ...
93
94
95
  
  int main(int argc, char **argv)
  {
84706caae   David Woodhouse   extract-cert: Cop...
96
  	char *cert_src;
1329e8cc6   David Woodhouse   modsign: Extract ...
97
98
99
100
  
  	OpenSSL_add_all_algorithms();
  	ERR_load_crypto_strings();
  	ERR_clear_error();
84706caae   David Woodhouse   extract-cert: Cop...
101
  	kbuild_verbose = atoi(getenv("KBUILD_VERBOSE")?:"0");
1329e8cc6   David Woodhouse   modsign: Extract ...
102
103
104
105
106
107
108
          key_pass = getenv("KBUILD_SIGN_PIN");
  
  	if (argc != 3)
  		format();
  
  	cert_src = argv[1];
  	cert_dst = argv[2];
84706caae   David Woodhouse   extract-cert: Cop...
109
110
111
112
113
114
115
  	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 ...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  		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...
137
  		write_cert(parms.cert);
1329e8cc6   David Woodhouse   modsign: Extract ...
138
  	} else {
84706caae   David Woodhouse   extract-cert: Cop...
139
140
  		BIO *b;
  		X509 *x509;
1329e8cc6   David Woodhouse   modsign: Extract ...
141
142
  		b = BIO_new_file(cert_src, "rb");
  		ERR(!b, "%s", cert_src);
84706caae   David Woodhouse   extract-cert: Cop...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  
  		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 ...
157
  	}
84706caae   David Woodhouse   extract-cert: Cop...
158
  	BIO_free(wb);
1329e8cc6   David Woodhouse   modsign: Extract ...
159
160
161
  
  	return 0;
  }