Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143365304
D18799.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D18799.diff
View Options
Index: usr.sbin/Makefile
===================================================================
--- usr.sbin/Makefile
+++ usr.sbin/Makefile
@@ -194,6 +194,7 @@
SUBDIR.${MK_QUOTAS}+= edquota
SUBDIR.${MK_QUOTAS}+= quotaon
SUBDIR.${MK_QUOTAS}+= repquota
+SUBDIR.${MK_SECUREBOOT}+= binsign
SUBDIR.${MK_SENDMAIL}+= editmap
SUBDIR.${MK_SENDMAIL}+= mailstats
SUBDIR.${MK_SENDMAIL}+= makemap
Index: usr.sbin/binsign/Makefile
===================================================================
--- /dev/null
+++ usr.sbin/binsign/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+PROG= binsign
+SRCS= binsign.c
+MAN= binsign.8
+
+LIBADD= secureboot bearssl
+
+WARNS= 6
+
+.include <bsd.prog.mk>
Index: usr.sbin/binsign/binsign.8
===================================================================
--- /dev/null
+++ usr.sbin/binsign/binsign.8
@@ -0,0 +1,95 @@
+.\"
+.\" Copyright (c) 2019 Stormshield.
+.\" Copyright (c) 2019 Semihalf.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"$FreeBSD$
+.Dd January 10, 2019
+.Dt BINSIGN 8
+.Os
+.Sh NAME
+.Nm binsign
+.Nd Secure Boot signing utility
+.Sh SYNOPSIS
+.Nm
+.Fl c Ar cert
+.Fl k Ar key
+.Op Fl o Ar output
+.Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility signs any type of file by appending a signature in PKCS#1 v1.5 standard
+together with a certificate used for the signing to its end.
+.Pp
+It is different from
+.Xr uefisign 8
+in that the former is used to sign PE binaries that are supposed to be verified
+and run directly by
+.Xr UEFI 8
+.Pp
+.Xr loader 8 can be configured by to verify the kernel and modules integrity
+signed with this tool. To do that one needs to compile it with
+.Nm -MK_SECUREBOOT="yes"
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success, and 1 if an error occurs.
+.Sh EXAMPLES
+.Bl -tag -width 0n
+.Pp
+.Li binsign -c cert.der -k cert.key file
+.Pp
+The
+.Pa cert.key
+and
+.Pa cert.der
+have to contain a DER encoded
+RSA private key and X509 certificate respectively, those can be generated with
+.Xr openssl 1
+.Sh SEE ALSO
+.Xr openssl 1
+.Xr loader 8
+.Xr uefisign 8
+.Xr UEFI 8
+.Sh STANDARDS
+.Bl -item
+.It
+.Rs
+.%A B. Kaliski
+.%T "PKCS #1: RSA Encryption Version 1.5"
+.%R RFC 2313
+.%D March 1998
+.Re
+.El
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 13.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was developed by
+.An Kornel Duleba Aq Mt mindal@semihalf.com
+under sponsorship from Stormshield.
Index: usr.sbin/binsign/binsign.c
===================================================================
--- /dev/null
+++ usr.sbin/binsign/binsign.c
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+
+#include <secureboot.h>
+
+static void usage() {
+ printf("binsign -c cert -k key [-o output] file\n");
+ exit(1);
+}
+
+static void
+gen_sha256(char* buffer, size_t length, unsigned char* output)
+{
+ br_hash_compat_context hash_ctx;
+ const br_hash_class *md;
+
+ md = &br_sha256_vtable;
+
+ md->init(&hash_ctx.vtable);
+ md->update(&hash_ctx.vtable, buffer, length);
+ md->out(&hash_ctx.vtable, output);
+}
+
+static int
+sign(char* cert, size_t cert_size, char* key, size_t key_size,
+ FILE *fp, unsigned char **output, size_t *output_size)
+{
+ struct stat sb;
+ struct signature_info sig_info;
+ unsigned char *buf = NULL;
+ int result;
+ unsigned char digest[br_sha256_SIZE];
+ br_skey_decoder_context ctx;
+ const br_rsa_private_key *priv;
+ unsigned int signature_length;
+
+ memset(&sb, 0, sizeof(sb));
+ memset(&sig_info, 0, sizeof(sig_info));
+
+ result = fstat(fileno(fp), &sb);
+ if (result != 0) {
+ result = errno;
+ printf("Fstat failed\n");
+ goto fail;
+ }
+
+ br_skey_decoder_init(&ctx);
+ br_skey_decoder_push(&ctx, key, key_size);
+ priv = br_skey_decoder_get_rsa(&ctx);
+ if (priv == NULL) {
+ printf("Failed to process private key\n");
+ result = EINVAL;
+ goto fail;
+ }
+
+ signature_length = (priv->n_bitlen + 7) >> 3;
+
+ buf = calloc(1, sb.st_size + signature_length + cert_size + sizeof(sig_info));
+ if (buf == NULL) {
+ printf("Failed to allocate memory\n");
+ result = ENOMEM;
+ goto fail;
+ }
+
+ if (fread(buf, sb.st_size, 1, fp) != 1) {
+ printf("Failed to read input file\n");
+ result = ferror(fp);
+ goto fail;
+ }
+
+ gen_sha256(buf, sb.st_size, digest);
+
+ result = br_rsa_pkcs1_sign_get_default()(
+ BR_HASH_OID_SHA256, digest, br_sha256_SIZE,
+ priv, buf + sb.st_size);
+ if (!result) {
+ printf("Failed to sign the digest\n");
+ result = EINVAL;
+ goto fail;
+ }
+
+ memcpy((buf + sb.st_size + signature_length), cert, cert_size);
+
+ sig_info.magic = MAGIC;
+ sig_info.kernel_size = sb.st_size;
+ sig_info.signature_size = signature_length;
+ sig_info.cert_size = cert_size;
+ memcpy((buf + sb.st_size + signature_length + cert_size), &sig_info, sizeof(sig_info));
+
+ *output_size = sb.st_size + signature_length + cert_size + sizeof(sig_info);
+ *output = buf;
+
+ return (0);
+
+fail:
+ if (buf != NULL)
+ free(buf);
+
+ return result;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ const char *cert_path, *key_path, *input_path, *output_path;
+ FILE *fp;
+ int result;
+ struct stat sb;
+ char *cert;
+ size_t cert_size, priv_size;
+ char *priv;
+ unsigned char *output;
+ size_t length;
+
+ cert_path = NULL;
+ key_path = NULL;
+ input_path = NULL;
+ output_path = NULL;
+ cert = NULL;
+ priv = NULL;
+ output = NULL;
+ fp = NULL;
+
+ while ((ch = getopt(argc, argv, "c:k:o:")) != -1) {
+ switch (ch) {
+ case 'c':
+ cert_path = strdup(optarg);
+ break;
+ case 'k':
+ key_path = strdup(optarg);
+ break;
+ case 'o':
+ output_path = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (cert_path == NULL) {
+ printf("-c option is mandatory\n");
+ usage();
+ }
+
+ if (key_path == NULL) {
+ printf("-k option is mandatory\n");
+ usage();
+ }
+
+ input_path = argv[optind];
+ if (output_path == NULL)
+ output_path = input_path;
+
+ fp = fopen(cert_path, "r");
+ if (fp == NULL) {
+ result = errno;
+ printf("Failed to open certificate file\n");
+ goto out;
+ }
+ result = fstat(fileno(fp), &sb);
+ if (result != 0) {
+ result = errno;
+ printf("Fstat failed\n");
+ goto out;
+ }
+ cert_size = sb.st_size;
+ cert = malloc(cert_size);
+ if (cert == NULL) {
+ result = errno;
+ printf("Failed to allocate memory\n");
+ goto out;
+ }
+ if (fread(cert, cert_size, 1, fp) != 1) {
+ result = ferror(fp);
+ printf("Failed to read the certificate\n");
+ goto out;
+ }
+ fclose(fp);
+
+ fp = fopen(key_path, "r");
+ if (fp == NULL) {
+ result = errno;
+ printf("Failed to open private key file\n");
+ goto out;
+ }
+ result = fstat(fileno(fp), &sb);
+ if (result != 0) {
+ result = errno;
+ printf("Fstat failed with\n");
+ goto out;
+
+ }
+ priv_size = sb.st_size;
+ priv = malloc(cert_size);
+ if (priv == NULL) {
+ result = ENOMEM;
+ printf("Failed to allocate memory\n");
+ goto out;
+ }
+ if (fread(priv, priv_size, 1, fp) != 1) {
+ result = ferror(fp);
+ printf("Failed to read private key\n");
+ goto out;
+ }
+ fclose(fp);
+
+ fp = fopen(input_path, "rb");
+ if (fp == NULL) {
+ result = errno;
+ printf("Failed to open input file\n");
+ goto out;
+ }
+
+ sign(cert, cert_size, priv, priv_size, fp, &output, &length);
+ if (result != 0)
+ goto out;
+
+ fclose(fp);
+
+ fp = fopen(output_path, "wb");
+ if (fp == NULL) {
+ result = errno;
+ printf("Failed to open output file\n");
+ goto out;
+ }
+
+ if (fwrite(output, length, 1, fp) != 1) {
+ result = ferror(fp);
+ printf("Failed to write the output file\n");
+ goto out;
+ }
+out:
+ if (fp != NULL)
+ fclose(fp);
+ if (cert != NULL)
+ free(cert);
+ if (priv != NULL)
+ free(priv);
+ if (output != NULL)
+ free(output);
+
+ exit(result);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 30, 11:28 AM (10 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28099831
Default Alt Text
D18799.diff (10 KB)
Attached To
Mode
D18799: Create binsign tool to sign binary files for Secure Boot
Attached
Detach File
Event Timeline
Log In to Comment