]> git.karo-electronics.de Git - karo-tx-linux.git/blob - scripts/extract-cert.c
4fd5b2f07b459ee43f59f2af3d5b7cbced6f0b48
[karo-tx-linux.git] / scripts / extract-cert.c
1 /* Extract X.509 certificate in DER form from PKCS#11 or PEM.
2  *
3  * Copyright © 2014 Red Hat, Inc. All Rights Reserved.
4  * Copyright © 2015 Intel Corporation.
5  *
6  * Authors: David Howells <dhowells@redhat.com>
7  *          David Woodhouse <dwmw2@infradead.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public Licence
11  * as published by the Free Software Foundation; either version
12  * 2 of the Licence, or (at your option) any later version.
13  */
14 #define _GNU_SOURCE
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <stdbool.h>
19 #include <string.h>
20 #include <getopt.h>
21 #include <err.h>
22 #include <arpa/inet.h>
23 #include <openssl/bio.h>
24 #include <openssl/evp.h>
25 #include <openssl/pem.h>
26 #include <openssl/pkcs7.h>
27 #include <openssl/err.h>
28 #include <openssl/engine.h>
29
30 #define PKEY_ID_PKCS7 2
31
32 static __attribute__((noreturn))
33 void format(void)
34 {
35         fprintf(stderr,
36                 "Usage: scripts/extract-cert <source> <dest>\n");
37         exit(2);
38 }
39
40 static void display_openssl_errors(int l)
41 {
42         const char *file;
43         char buf[120];
44         int e, line;
45
46         if (ERR_peek_error() == 0)
47                 return;
48         fprintf(stderr, "At main.c:%d:\n", l);
49
50         while ((e = ERR_get_error_line(&file, &line))) {
51                 ERR_error_string(e, buf);
52                 fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
53         }
54 }
55
56 static void drain_openssl_errors(void)
57 {
58         const char *file;
59         int line;
60
61         if (ERR_peek_error() == 0)
62                 return;
63         while (ERR_get_error_line(&file, &line)) {}
64 }
65
66 #define ERR(cond, fmt, ...)                             \
67         do {                                            \
68                 bool __cond = (cond);                   \
69                 display_openssl_errors(__LINE__);       \
70                 if (__cond) {                           \
71                         err(1, fmt, ## __VA_ARGS__);    \
72                 }                                       \
73         } while(0)
74
75 static const char *key_pass;
76
77 int main(int argc, char **argv)
78 {
79         char *cert_src, *cert_dst;
80         X509 *x509;
81         BIO *b;
82
83         OpenSSL_add_all_algorithms();
84         ERR_load_crypto_strings();
85         ERR_clear_error();
86
87         key_pass = getenv("KBUILD_SIGN_PIN");
88
89         if (argc != 3)
90                 format();
91
92         cert_src = argv[1];
93         cert_dst = argv[2];
94
95         if (!strncmp(cert_src, "pkcs11:", 7)) {
96                 ENGINE *e;
97                 struct {
98                         const char *cert_id;
99                         X509 *cert;
100                 } parms;
101
102                 parms.cert_id = cert_src;
103                 parms.cert = NULL;
104
105                 ENGINE_load_builtin_engines();
106                 drain_openssl_errors();
107                 e = ENGINE_by_id("pkcs11");
108                 ERR(!e, "Load PKCS#11 ENGINE");
109                 if (ENGINE_init(e))
110                         drain_openssl_errors();
111                 else
112                         ERR(1, "ENGINE_init");
113                 if (key_pass)
114                         ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
115                 ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1);
116                 ERR(!parms.cert, "Get X.509 from PKCS#11");
117                 x509 = parms.cert;
118         } else {
119                 b = BIO_new_file(cert_src, "rb");
120                 ERR(!b, "%s", cert_src);
121                 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
122                 ERR(!x509, "%s", cert_src);
123                 BIO_free(b);
124         }
125
126         b = BIO_new_file(cert_dst, "wb");
127         ERR(!b, "%s", cert_dst);
128         ERR(!i2d_X509_bio(b, x509), cert_dst);
129         BIO_free(b);
130
131         return 0;
132 }