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