at for-next 4.3 kB view raw
1/* Extract X.509 certificate in DER form from PKCS#11 or PEM. 2 * 3 * Copyright © 2014-2015 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 Lesser General Public License 11 * as published by the Free Software Foundation; either version 2.1 12 * 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 <err.h> 21#include <openssl/bio.h> 22#include <openssl/pem.h> 23#include <openssl/err.h> 24#if OPENSSL_VERSION_MAJOR >= 3 25# define USE_PKCS11_PROVIDER 26# include <openssl/provider.h> 27# include <openssl/store.h> 28#else 29# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) 30# define USE_PKCS11_ENGINE 31# include <openssl/engine.h> 32# endif 33#endif 34#include "ssl-common.h" 35 36#define PKEY_ID_PKCS7 2 37 38static __attribute__((noreturn)) 39void format(void) 40{ 41 fprintf(stderr, 42 "Usage: extract-cert <source> <dest>\n"); 43 exit(2); 44} 45 46static const char *key_pass; 47static BIO *wb; 48static char *cert_dst; 49static bool verbose; 50 51static void write_cert(X509 *x509) 52{ 53 char buf[200]; 54 55 if (!wb) { 56 wb = BIO_new_file(cert_dst, "wb"); 57 ERR(!wb, "%s", cert_dst); 58 } 59 X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf)); 60 ERR(!i2d_X509_bio(wb, x509), "%s", cert_dst); 61 if (verbose) 62 fprintf(stderr, "Extracted cert: %s\n", buf); 63} 64 65static X509 *load_cert_pkcs11(const char *cert_src) 66{ 67 X509 *cert = NULL; 68#ifdef USE_PKCS11_PROVIDER 69 OSSL_STORE_CTX *store; 70 71 if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true)) 72 ERR(1, "OSSL_PROVIDER_try_load(pkcs11)"); 73 if (!OSSL_PROVIDER_try_load(NULL, "default", true)) 74 ERR(1, "OSSL_PROVIDER_try_load(default)"); 75 76 store = OSSL_STORE_open(cert_src, NULL, NULL, NULL, NULL); 77 ERR(!store, "OSSL_STORE_open"); 78 79 while (!OSSL_STORE_eof(store)) { 80 OSSL_STORE_INFO *info = OSSL_STORE_load(store); 81 82 if (!info) { 83 drain_openssl_errors(__LINE__, 0); 84 continue; 85 } 86 if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_CERT) { 87 cert = OSSL_STORE_INFO_get1_CERT(info); 88 ERR(!cert, "OSSL_STORE_INFO_get1_CERT"); 89 } 90 OSSL_STORE_INFO_free(info); 91 if (cert) 92 break; 93 } 94 OSSL_STORE_close(store); 95#elif defined(USE_PKCS11_ENGINE) 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(__LINE__, 1); 107 e = ENGINE_by_id("pkcs11"); 108 ERR(!e, "Load PKCS#11 ENGINE"); 109 if (ENGINE_init(e)) 110 drain_openssl_errors(__LINE__, 1); 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 cert = parms.cert; 118#else 119 fprintf(stderr, "no pkcs11 engine/provider available\n"); 120 exit(1); 121#endif 122 return cert; 123} 124 125int main(int argc, char **argv) 126{ 127 char *cert_src; 128 char *verbose_env; 129 130 OpenSSL_add_all_algorithms(); 131 ERR_load_crypto_strings(); 132 ERR_clear_error(); 133 134 verbose_env = getenv("KBUILD_VERBOSE"); 135 if (verbose_env && strchr(verbose_env, '1')) 136 verbose = true; 137 138 key_pass = getenv("KBUILD_SIGN_PIN"); 139 140 if (argc != 3) 141 format(); 142 143 cert_src = argv[1]; 144 cert_dst = argv[2]; 145 146 if (!cert_src[0]) { 147 /* Invoked with no input; create empty file */ 148 FILE *f = fopen(cert_dst, "wb"); 149 ERR(!f, "%s", cert_dst); 150 fclose(f); 151 exit(0); 152 } else if (!strncmp(cert_src, "pkcs11:", 7)) { 153 X509 *cert = load_cert_pkcs11(cert_src); 154 155 ERR(!cert, "load_cert_pkcs11 failed"); 156 write_cert(cert); 157 } else { 158 BIO *b; 159 X509 *x509; 160 161 b = BIO_new_file(cert_src, "rb"); 162 ERR(!b, "%s", cert_src); 163 164 while (1) { 165 x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); 166 if (wb && !x509) { 167 unsigned long err = ERR_peek_last_error(); 168 if (ERR_GET_LIB(err) == ERR_LIB_PEM && 169 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { 170 ERR_clear_error(); 171 break; 172 } 173 } 174 ERR(!x509, "%s", cert_src); 175 write_cert(x509); 176 } 177 } 178 179 BIO_free(wb); 180 181 return 0; 182}