162306a36Sopenharmony_ci/* Sign a module file using the given key. 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * Copyright © 2014-2016 Red Hat, Inc. All Rights Reserved. 462306a36Sopenharmony_ci * Copyright © 2015 Intel Corporation. 562306a36Sopenharmony_ci * Copyright © 2016 Hewlett Packard Enterprise Development LP 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: David Howells <dhowells@redhat.com> 862306a36Sopenharmony_ci * David Woodhouse <dwmw2@infradead.org> 962306a36Sopenharmony_ci * Juerg Haefliger <juerg.haefliger@hpe.com> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or 1262306a36Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public License 1362306a36Sopenharmony_ci * as published by the Free Software Foundation; either version 2.1 1462306a36Sopenharmony_ci * of the licence, or (at your option) any later version. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci#define _GNU_SOURCE 1762306a36Sopenharmony_ci#include <stdio.h> 1862306a36Sopenharmony_ci#include <stdlib.h> 1962306a36Sopenharmony_ci#include <stdint.h> 2062306a36Sopenharmony_ci#include <stdbool.h> 2162306a36Sopenharmony_ci#include <string.h> 2262306a36Sopenharmony_ci#include <getopt.h> 2362306a36Sopenharmony_ci#include <err.h> 2462306a36Sopenharmony_ci#include <arpa/inet.h> 2562306a36Sopenharmony_ci#include <openssl/opensslv.h> 2662306a36Sopenharmony_ci#include <openssl/bio.h> 2762306a36Sopenharmony_ci#include <openssl/evp.h> 2862306a36Sopenharmony_ci#include <openssl/pem.h> 2962306a36Sopenharmony_ci#include <openssl/err.h> 3062306a36Sopenharmony_ci#include <openssl/engine.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Remove this if/when that API is no longer used 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to 4162306a36Sopenharmony_ci * assume that it's not available and its header file is missing and that we 4262306a36Sopenharmony_ci * should use PKCS#7 instead. Switching to the older PKCS#7 format restricts 4362306a36Sopenharmony_ci * the options we have on specifying the X.509 certificate we want. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * Further, older versions of OpenSSL don't support manually adding signers to 4662306a36Sopenharmony_ci * the PKCS#7 message so have to accept that we get a certificate included in 4762306a36Sopenharmony_ci * the signature message. Nor do such older versions of OpenSSL support 4862306a36Sopenharmony_ci * signing with anything other than SHA1 - so we're stuck with that if such is 4962306a36Sopenharmony_ci * the case. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#if defined(LIBRESSL_VERSION_NUMBER) || \ 5262306a36Sopenharmony_ci OPENSSL_VERSION_NUMBER < 0x10000000L || \ 5362306a36Sopenharmony_ci defined(OPENSSL_NO_CMS) 5462306a36Sopenharmony_ci#define USE_PKCS7 5562306a36Sopenharmony_ci#endif 5662306a36Sopenharmony_ci#ifndef USE_PKCS7 5762306a36Sopenharmony_ci#include <openssl/cms.h> 5862306a36Sopenharmony_ci#else 5962306a36Sopenharmony_ci#include <openssl/pkcs7.h> 6062306a36Sopenharmony_ci#endif 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistruct module_signature { 6362306a36Sopenharmony_ci uint8_t algo; /* Public-key crypto algorithm [0] */ 6462306a36Sopenharmony_ci uint8_t hash; /* Digest algorithm [0] */ 6562306a36Sopenharmony_ci uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 6662306a36Sopenharmony_ci uint8_t signer_len; /* Length of signer's name [0] */ 6762306a36Sopenharmony_ci uint8_t key_id_len; /* Length of key identifier [0] */ 6862306a36Sopenharmony_ci uint8_t __pad[3]; 6962306a36Sopenharmony_ci uint32_t sig_len; /* Length of signature data */ 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#define PKEY_ID_PKCS7 2 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic char magic_number[] = "~Module signature appended~\n"; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic __attribute__((noreturn)) 7762306a36Sopenharmony_civoid format(void) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci fprintf(stderr, 8062306a36Sopenharmony_ci "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); 8162306a36Sopenharmony_ci fprintf(stderr, 8262306a36Sopenharmony_ci " scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n"); 8362306a36Sopenharmony_ci exit(2); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void display_openssl_errors(int l) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci const char *file; 8962306a36Sopenharmony_ci char buf[120]; 9062306a36Sopenharmony_ci int e, line; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (ERR_peek_error() == 0) 9362306a36Sopenharmony_ci return; 9462306a36Sopenharmony_ci fprintf(stderr, "At main.c:%d:\n", l); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci while ((e = ERR_get_error_line(&file, &line))) { 9762306a36Sopenharmony_ci ERR_error_string(e, buf); 9862306a36Sopenharmony_ci fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic void drain_openssl_errors(void) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci const char *file; 10562306a36Sopenharmony_ci int line; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (ERR_peek_error() == 0) 10862306a36Sopenharmony_ci return; 10962306a36Sopenharmony_ci while (ERR_get_error_line(&file, &line)) {} 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define ERR(cond, fmt, ...) \ 11362306a36Sopenharmony_ci do { \ 11462306a36Sopenharmony_ci bool __cond = (cond); \ 11562306a36Sopenharmony_ci display_openssl_errors(__LINE__); \ 11662306a36Sopenharmony_ci if (__cond) { \ 11762306a36Sopenharmony_ci errx(1, fmt, ## __VA_ARGS__); \ 11862306a36Sopenharmony_ci } \ 11962306a36Sopenharmony_ci } while(0) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic const char *key_pass; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic int pem_pw_cb(char *buf, int len, int w, void *v) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci int pwlen; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (!key_pass) 12862306a36Sopenharmony_ci return -1; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci pwlen = strlen(key_pass); 13162306a36Sopenharmony_ci if (pwlen >= len) 13262306a36Sopenharmony_ci return -1; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci strcpy(buf, key_pass); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* If it's wrong, don't keep trying it. */ 13762306a36Sopenharmony_ci key_pass = NULL; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return pwlen; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic EVP_PKEY *read_private_key(const char *private_key_name) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci EVP_PKEY *private_key; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (!strncmp(private_key_name, "pkcs11:", 7)) { 14762306a36Sopenharmony_ci ENGINE *e; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ENGINE_load_builtin_engines(); 15062306a36Sopenharmony_ci drain_openssl_errors(); 15162306a36Sopenharmony_ci e = ENGINE_by_id("pkcs11"); 15262306a36Sopenharmony_ci ERR(!e, "Load PKCS#11 ENGINE"); 15362306a36Sopenharmony_ci if (ENGINE_init(e)) 15462306a36Sopenharmony_ci drain_openssl_errors(); 15562306a36Sopenharmony_ci else 15662306a36Sopenharmony_ci ERR(1, "ENGINE_init"); 15762306a36Sopenharmony_ci if (key_pass) 15862306a36Sopenharmony_ci ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), 15962306a36Sopenharmony_ci "Set PKCS#11 PIN"); 16062306a36Sopenharmony_ci private_key = ENGINE_load_private_key(e, private_key_name, 16162306a36Sopenharmony_ci NULL, NULL); 16262306a36Sopenharmony_ci ERR(!private_key, "%s", private_key_name); 16362306a36Sopenharmony_ci } else { 16462306a36Sopenharmony_ci BIO *b; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci b = BIO_new_file(private_key_name, "rb"); 16762306a36Sopenharmony_ci ERR(!b, "%s", private_key_name); 16862306a36Sopenharmony_ci private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, 16962306a36Sopenharmony_ci NULL); 17062306a36Sopenharmony_ci ERR(!private_key, "%s", private_key_name); 17162306a36Sopenharmony_ci BIO_free(b); 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return private_key; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic X509 *read_x509(const char *x509_name) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci unsigned char buf[2]; 18062306a36Sopenharmony_ci X509 *x509; 18162306a36Sopenharmony_ci BIO *b; 18262306a36Sopenharmony_ci int n; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci b = BIO_new_file(x509_name, "rb"); 18562306a36Sopenharmony_ci ERR(!b, "%s", x509_name); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* Look at the first two bytes of the file to determine the encoding */ 18862306a36Sopenharmony_ci n = BIO_read(b, buf, 2); 18962306a36Sopenharmony_ci if (n != 2) { 19062306a36Sopenharmony_ci if (BIO_should_retry(b)) { 19162306a36Sopenharmony_ci fprintf(stderr, "%s: Read wanted retry\n", x509_name); 19262306a36Sopenharmony_ci exit(1); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci if (n >= 0) { 19562306a36Sopenharmony_ci fprintf(stderr, "%s: Short read\n", x509_name); 19662306a36Sopenharmony_ci exit(1); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci ERR(1, "%s", x509_name); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ERR(BIO_reset(b) != 0, "%s", x509_name); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84) 20462306a36Sopenharmony_ci /* Assume raw DER encoded X.509 */ 20562306a36Sopenharmony_ci x509 = d2i_X509_bio(b, NULL); 20662306a36Sopenharmony_ci else 20762306a36Sopenharmony_ci /* Assume PEM encoded X.509 */ 20862306a36Sopenharmony_ci x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci BIO_free(b); 21162306a36Sopenharmony_ci ERR(!x509, "%s", x509_name); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci return x509; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ciint main(int argc, char **argv) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 }; 21962306a36Sopenharmony_ci char *hash_algo = NULL; 22062306a36Sopenharmony_ci char *private_key_name = NULL, *raw_sig_name = NULL; 22162306a36Sopenharmony_ci char *x509_name, *module_name, *dest_name; 22262306a36Sopenharmony_ci bool save_sig = false, replace_orig; 22362306a36Sopenharmony_ci bool sign_only = false; 22462306a36Sopenharmony_ci bool raw_sig = false; 22562306a36Sopenharmony_ci unsigned char buf[4096]; 22662306a36Sopenharmony_ci unsigned long module_size, sig_size; 22762306a36Sopenharmony_ci unsigned int use_signed_attrs; 22862306a36Sopenharmony_ci const EVP_MD *digest_algo; 22962306a36Sopenharmony_ci EVP_PKEY *private_key; 23062306a36Sopenharmony_ci#ifndef USE_PKCS7 23162306a36Sopenharmony_ci CMS_ContentInfo *cms = NULL; 23262306a36Sopenharmony_ci unsigned int use_keyid = 0; 23362306a36Sopenharmony_ci#else 23462306a36Sopenharmony_ci PKCS7 *pkcs7 = NULL; 23562306a36Sopenharmony_ci#endif 23662306a36Sopenharmony_ci X509 *x509; 23762306a36Sopenharmony_ci BIO *bd, *bm; 23862306a36Sopenharmony_ci int opt, n; 23962306a36Sopenharmony_ci OpenSSL_add_all_algorithms(); 24062306a36Sopenharmony_ci ERR_load_crypto_strings(); 24162306a36Sopenharmony_ci ERR_clear_error(); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci key_pass = getenv("KBUILD_SIGN_PIN"); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci#ifndef USE_PKCS7 24662306a36Sopenharmony_ci use_signed_attrs = CMS_NOATTR; 24762306a36Sopenharmony_ci#else 24862306a36Sopenharmony_ci use_signed_attrs = PKCS7_NOATTR; 24962306a36Sopenharmony_ci#endif 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci do { 25262306a36Sopenharmony_ci opt = getopt(argc, argv, "sdpk"); 25362306a36Sopenharmony_ci switch (opt) { 25462306a36Sopenharmony_ci case 's': raw_sig = true; break; 25562306a36Sopenharmony_ci case 'p': save_sig = true; break; 25662306a36Sopenharmony_ci case 'd': sign_only = true; save_sig = true; break; 25762306a36Sopenharmony_ci#ifndef USE_PKCS7 25862306a36Sopenharmony_ci case 'k': use_keyid = CMS_USE_KEYID; break; 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci case -1: break; 26162306a36Sopenharmony_ci default: format(); 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci } while (opt != -1); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci argc -= optind; 26662306a36Sopenharmony_ci argv += optind; 26762306a36Sopenharmony_ci if (argc < 4 || argc > 5) 26862306a36Sopenharmony_ci format(); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (raw_sig) { 27162306a36Sopenharmony_ci raw_sig_name = argv[0]; 27262306a36Sopenharmony_ci hash_algo = argv[1]; 27362306a36Sopenharmony_ci } else { 27462306a36Sopenharmony_ci hash_algo = argv[0]; 27562306a36Sopenharmony_ci private_key_name = argv[1]; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci x509_name = argv[2]; 27862306a36Sopenharmony_ci module_name = argv[3]; 27962306a36Sopenharmony_ci if (argc == 5 && strcmp(argv[3], argv[4]) != 0) { 28062306a36Sopenharmony_ci dest_name = argv[4]; 28162306a36Sopenharmony_ci replace_orig = false; 28262306a36Sopenharmony_ci } else { 28362306a36Sopenharmony_ci ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0, 28462306a36Sopenharmony_ci "asprintf"); 28562306a36Sopenharmony_ci replace_orig = true; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci#ifdef USE_PKCS7 28962306a36Sopenharmony_ci if (strcmp(hash_algo, "sha1") != 0) { 29062306a36Sopenharmony_ci fprintf(stderr, "sign-file: %s only supports SHA1 signing\n", 29162306a36Sopenharmony_ci OPENSSL_VERSION_TEXT); 29262306a36Sopenharmony_ci exit(3); 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci#endif 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Open the module file */ 29762306a36Sopenharmony_ci bm = BIO_new_file(module_name, "rb"); 29862306a36Sopenharmony_ci ERR(!bm, "%s", module_name); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (!raw_sig) { 30162306a36Sopenharmony_ci /* Read the private key and the X.509 cert the PKCS#7 message 30262306a36Sopenharmony_ci * will point to. 30362306a36Sopenharmony_ci */ 30462306a36Sopenharmony_ci private_key = read_private_key(private_key_name); 30562306a36Sopenharmony_ci x509 = read_x509(x509_name); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* Digest the module data. */ 30862306a36Sopenharmony_ci OpenSSL_add_all_digests(); 30962306a36Sopenharmony_ci display_openssl_errors(__LINE__); 31062306a36Sopenharmony_ci digest_algo = EVP_get_digestbyname(hash_algo); 31162306a36Sopenharmony_ci ERR(!digest_algo, "EVP_get_digestbyname"); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci#ifndef USE_PKCS7 31462306a36Sopenharmony_ci /* Load the signature message from the digest buffer. */ 31562306a36Sopenharmony_ci cms = CMS_sign(NULL, NULL, NULL, NULL, 31662306a36Sopenharmony_ci CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | 31762306a36Sopenharmony_ci CMS_DETACHED | CMS_STREAM); 31862306a36Sopenharmony_ci ERR(!cms, "CMS_sign"); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, 32162306a36Sopenharmony_ci CMS_NOCERTS | CMS_BINARY | 32262306a36Sopenharmony_ci CMS_NOSMIMECAP | use_keyid | 32362306a36Sopenharmony_ci use_signed_attrs), 32462306a36Sopenharmony_ci "CMS_add1_signer"); 32562306a36Sopenharmony_ci ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) != 1, 32662306a36Sopenharmony_ci "CMS_final"); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci#else 32962306a36Sopenharmony_ci pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, 33062306a36Sopenharmony_ci PKCS7_NOCERTS | PKCS7_BINARY | 33162306a36Sopenharmony_ci PKCS7_DETACHED | use_signed_attrs); 33262306a36Sopenharmony_ci ERR(!pkcs7, "PKCS7_sign"); 33362306a36Sopenharmony_ci#endif 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (save_sig) { 33662306a36Sopenharmony_ci char *sig_file_name; 33762306a36Sopenharmony_ci BIO *b; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, 34062306a36Sopenharmony_ci "asprintf"); 34162306a36Sopenharmony_ci b = BIO_new_file(sig_file_name, "wb"); 34262306a36Sopenharmony_ci ERR(!b, "%s", sig_file_name); 34362306a36Sopenharmony_ci#ifndef USE_PKCS7 34462306a36Sopenharmony_ci ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) != 1, 34562306a36Sopenharmony_ci "%s", sig_file_name); 34662306a36Sopenharmony_ci#else 34762306a36Sopenharmony_ci ERR(i2d_PKCS7_bio(b, pkcs7) != 1, 34862306a36Sopenharmony_ci "%s", sig_file_name); 34962306a36Sopenharmony_ci#endif 35062306a36Sopenharmony_ci BIO_free(b); 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (sign_only) { 35462306a36Sopenharmony_ci BIO_free(bm); 35562306a36Sopenharmony_ci return 0; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* Open the destination file now so that we can shovel the module data 36062306a36Sopenharmony_ci * across as we read it. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci bd = BIO_new_file(dest_name, "wb"); 36362306a36Sopenharmony_ci ERR(!bd, "%s", dest_name); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* Append the marker and the PKCS#7 message to the destination file */ 36662306a36Sopenharmony_ci ERR(BIO_reset(bm) < 0, "%s", module_name); 36762306a36Sopenharmony_ci while ((n = BIO_read(bm, buf, sizeof(buf))), 36862306a36Sopenharmony_ci n > 0) { 36962306a36Sopenharmony_ci ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci BIO_free(bm); 37262306a36Sopenharmony_ci ERR(n < 0, "%s", module_name); 37362306a36Sopenharmony_ci module_size = BIO_number_written(bd); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (!raw_sig) { 37662306a36Sopenharmony_ci#ifndef USE_PKCS7 37762306a36Sopenharmony_ci ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) != 1, "%s", dest_name); 37862306a36Sopenharmony_ci#else 37962306a36Sopenharmony_ci ERR(i2d_PKCS7_bio(bd, pkcs7) != 1, "%s", dest_name); 38062306a36Sopenharmony_ci#endif 38162306a36Sopenharmony_ci } else { 38262306a36Sopenharmony_ci BIO *b; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* Read the raw signature file and write the data to the 38562306a36Sopenharmony_ci * destination file 38662306a36Sopenharmony_ci */ 38762306a36Sopenharmony_ci b = BIO_new_file(raw_sig_name, "rb"); 38862306a36Sopenharmony_ci ERR(!b, "%s", raw_sig_name); 38962306a36Sopenharmony_ci while ((n = BIO_read(b, buf, sizeof(buf))), n > 0) 39062306a36Sopenharmony_ci ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); 39162306a36Sopenharmony_ci BIO_free(b); 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci sig_size = BIO_number_written(bd) - module_size; 39562306a36Sopenharmony_ci sig_info.sig_len = htonl(sig_size); 39662306a36Sopenharmony_ci ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name); 39762306a36Sopenharmony_ci ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci ERR(BIO_free(bd) != 1, "%s", dest_name); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Finally, if we're signing in place, replace the original. */ 40262306a36Sopenharmony_ci if (replace_orig) 40362306a36Sopenharmony_ci ERR(rename(dest_name, module_name) < 0, "%s", dest_name); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci} 407