169990Sdes/*- 269990Sdes * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 369990Sdes * 469990Sdes * Copyright (c) 2014 The FreeBSD Foundation 569990Sdes * All rights reserved. 669990Sdes * 769990Sdes * This software was developed by Edward Tomasz Napierala under sponsorship 869990Sdes * from the FreeBSD Foundation. 969990Sdes * 1069990Sdes * Redistribution and use in source and binary forms, with or without 1169990Sdes * modification, are permitted provided that the following conditions 1269990Sdes * are met: 1369990Sdes * 1. Redistributions of source code must retain the above copyright 1469990Sdes * notice, this list of conditions and the following disclaimer. 1569990Sdes * 2. Redistributions in binary form must reproduce the above copyright 1669990Sdes * notice, this list of conditions and the following disclaimer in the 1769990Sdes * documentation and/or other materials provided with the distribution. 1869990Sdes * 1969990Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2069990Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2169990Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2269990Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2369990Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2469990Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2569990Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2669990Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2769990Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2869990Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2969990Sdes * SUCH DAMAGE. 3069990Sdes * 3169990Sdes */ 3274840Sken 3374840Sken#include <sys/cdefs.h> 3474840Sken__FBSDID("$FreeBSD: stable/11/usr.sbin/uefisign/child.c 332615 2018-04-16 17:13:54Z trasz $"); 3569990Sdes 3669990Sdes#include <sys/param.h> 3769990Sdes#if __FreeBSD_version >= 1100000 3869990Sdes#include <sys/capsicum.h> 3974840Sken#else 4074840Sken#include <sys/capability.h> 4174840Sken#endif 4269990Sdes#include <sys/types.h> 4374840Sken#include <sys/stat.h> 4469990Sdes#include <assert.h> 4574840Sken#include <err.h> 4674840Sken#include <errno.h> 4774840Sken#include <stdio.h> 4874840Sken#include <stdlib.h> 4974840Sken#include <string.h> 5074840Sken#include <unistd.h> 5174840Sken 5274840Sken#include <openssl/evp.h> 5369990Sdes#include <openssl/err.h> 5471721Sdes#include <openssl/pem.h> 5571721Sdes 5671721Sdes#include "uefisign.h" 5771721Sdes 5871721Sdesstatic void 5971721Sdesload(struct executable *x) 6071721Sdes{ 6171721Sdes int error, fd; 6271721Sdes struct stat sb; 6371721Sdes char *buf; 6471721Sdes size_t nread, len; 6571721Sdes 6671721Sdes fd = fileno(x->x_fp); 6771721Sdes 6871721Sdes error = fstat(fd, &sb); 6971721Sdes if (error != 0) 7071721Sdes err(1, "%s: fstat", x->x_path); 7174840Sken 7269990Sdes len = sb.st_size; 7373891Sdes if (len <= 0) 7469990Sdes errx(1, "%s: file is empty", x->x_path); 7569990Sdes 7673891Sdes buf = malloc(len); 7769990Sdes if (buf == NULL) 7873891Sdes err(1, "%s: cannot malloc %zd bytes", x->x_path, len); 7969990Sdes 8069990Sdes nread = fread(buf, len, 1, x->x_fp); 8169990Sdes if (nread != 1) 8269990Sdes err(1, "%s: fread", x->x_path); 8369990Sdes 8473891Sdes x->x_buf = buf; 8569990Sdes x->x_len = len; 8669990Sdes} 8773891Sdes 8869990Sdesstatic void 8969990Sdesdigest_range(struct executable *x, EVP_MD_CTX *mdctx, off_t off, size_t len) 9073891Sdes{ 9173891Sdes int ok; 9274840Sken 9369990Sdes range_check(x, off, len, "chunk"); 9469990Sdes 9574840Sken ok = EVP_DigestUpdate(mdctx, x->x_buf + off, len); 9669990Sdes if (ok == 0) { 9769990Sdes ERR_print_errors_fp(stderr); 9869990Sdes errx(1, "EVP_DigestUpdate(3) failed"); 9969990Sdes } 10069990Sdes} 10169990Sdes 10269990Sdesstatic void 10371721Sdesdigest(struct executable *x) 10469990Sdes{ 10571721Sdes EVP_MD_CTX *mdctx; 10671721Sdes const EVP_MD *md; 10769990Sdes size_t sum_of_bytes_hashed; 10869990Sdes int i, ok; 10969990Sdes 11069990Sdes /* 11169990Sdes * Windows Authenticode Portable Executable Signature Format 11269990Sdes * spec version 1.0 specifies MD5 and SHA1. However, pesign 11369990Sdes * and sbsign both use SHA256, so do the same. 11469990Sdes */ 11569990Sdes md = EVP_get_digestbyname(DIGEST); 11669990Sdes if (md == NULL) { 11769990Sdes ERR_print_errors_fp(stderr); 11874840Sken errx(1, "EVP_get_digestbyname(\"%s\") failed", DIGEST); 11969990Sdes } 12069990Sdes 12169990Sdes mdctx = EVP_MD_CTX_create(); 12269990Sdes if (mdctx == NULL) { 12369990Sdes ERR_print_errors_fp(stderr); 12469990Sdes errx(1, "EVP_MD_CTX_create(3) failed"); 12569990Sdes } 12671721Sdes 12771721Sdes ok = EVP_DigestInit_ex(mdctx, md, NULL); 12871721Sdes if (ok == 0) { 12971721Sdes ERR_print_errors_fp(stderr); 13071721Sdes errx(1, "EVP_DigestInit_ex(3) failed"); 13171721Sdes } 13271724Sdes 13371721Sdes /* 13471721Sdes * According to the Authenticode spec, we need to compute 13571721Sdes * the digest in a rather... specific manner; see "Calculating 13671721Sdes * the PE Image Hash" part of the spec for details. 13771721Sdes * 13871721Sdes * First, everything from 0 to before the PE checksum. 13971721Sdes */ 14069990Sdes digest_range(x, mdctx, 0, x->x_checksum_off); 14169990Sdes 14269990Sdes /* 14371721Sdes * Second, from after the PE checksum to before the Certificate 14469990Sdes * entry in Data Directory. 14569990Sdes */ 14669990Sdes digest_range(x, mdctx, x->x_checksum_off + x->x_checksum_len, 14769990Sdes x->x_certificate_entry_off - 14869990Sdes (x->x_checksum_off + x->x_checksum_len)); 14969990Sdes 15069990Sdes /* 15169990Sdes * Then, from after the Certificate entry to the end of headers. 15269990Sdes */ 15369990Sdes digest_range(x, mdctx, 15469990Sdes x->x_certificate_entry_off + x->x_certificate_entry_len, 15569990Sdes x->x_headers_len - 15669990Sdes (x->x_certificate_entry_off + x->x_certificate_entry_len)); 15769990Sdes 15869990Sdes /* 15969990Sdes * Then, each section in turn, as specified in the PE Section Table. 16069990Sdes * 16169990Sdes * XXX: Sorting. 16269990Sdes */ 16374840Sken sum_of_bytes_hashed = x->x_headers_len; 16469990Sdes for (i = 0; i < x->x_nsections; i++) { 16569990Sdes digest_range(x, mdctx, 16669990Sdes x->x_section_off[i], x->x_section_len[i]); 16769990Sdes sum_of_bytes_hashed += x->x_section_len[i]; 16869990Sdes } 16969990Sdes 17069990Sdes /* 17169990Sdes * I believe this can happen with overlapping sections. 17269990Sdes */ 17369990Sdes if (sum_of_bytes_hashed > x->x_len) 17469990Sdes errx(1, "number of bytes hashed is larger than file size"); 17569990Sdes 17669990Sdes /* 17769990Sdes * I can't really explain this one; just do what the spec says. 17869990Sdes */ 17969990Sdes if (sum_of_bytes_hashed < x->x_len) { 18069990Sdes digest_range(x, mdctx, sum_of_bytes_hashed, 18169990Sdes x->x_len - (signature_size(x) + sum_of_bytes_hashed)); 18269990Sdes } 18369990Sdes 18474840Sken ok = EVP_DigestFinal_ex(mdctx, x->x_digest, &x->x_digest_len); 18569990Sdes if (ok == 0) { 18669990Sdes ERR_print_errors_fp(stderr); 18769990Sdes errx(1, "EVP_DigestFinal_ex(3) failed"); 18869990Sdes } 18971721Sdes 19069990Sdes EVP_MD_CTX_destroy(mdctx); 19169990Sdes} 19269990Sdes 19369990Sdesstatic void 19469990Sdesshow_digest(const struct executable *x) 19569990Sdes{ 19669990Sdes int i; 19769990Sdes 19869990Sdes printf("computed %s digest ", DIGEST); 19969990Sdes for (i = 0; i < (int)x->x_digest_len; i++) 20071721Sdes printf("%02x", (unsigned char)x->x_digest[i]); 20169990Sdes printf("; digest len %u\n", x->x_digest_len); 20269990Sdes} 20369990Sdes 20469990Sdesstatic void 20569990Sdessend_digest(const struct executable *x, int pipefd) 20669990Sdes{ 20769990Sdes 20869990Sdes send_chunk(x->x_digest, x->x_digest_len, pipefd); 20969990Sdes} 21069990Sdes 21169990Sdesstatic void 21274840Skenreceive_signature(struct executable *x, int pipefd) 21369990Sdes{ 21469990Sdes 21574840Sken receive_chunk(&x->x_signature, &x->x_signature_len, pipefd); 21674840Sken} 21774840Sken 21874840Skenstatic void 21974840Skensave(struct executable *x, FILE *fp, const char *path) 22074840Sken{ 22174840Sken size_t nwritten; 22274840Sken 22374840Sken assert(fp != NULL); 22474840Sken assert(path != NULL); 22574840Sken 22674840Sken nwritten = fwrite(x->x_buf, x->x_len, 1, fp); 22774840Sken if (nwritten != 1) 22869990Sdes err(1, "%s: fwrite", path); 22969990Sdes} 23069990Sdes 23169990Sdesint 23269990Sdeschild(const char *inpath, const char *outpath, int pipefd, 23369990Sdes bool Vflag, bool vflag) 23469990Sdes{ 23569990Sdes int error; 23669990Sdes FILE *outfp = NULL, *infp = NULL; 23769990Sdes struct executable *x; 23869990Sdes 23969990Sdes infp = checked_fopen(inpath, "r"); 24069990Sdes if (outpath != NULL) 24169990Sdes outfp = checked_fopen(outpath, "w"); 24269990Sdes 24369990Sdes error = cap_enter(); 24469990Sdes if (error != 0 && errno != ENOSYS) 24569990Sdes err(1, "cap_enter"); 24669990Sdes 24769990Sdes x = calloc(1, sizeof(*x)); 24869990Sdes if (x == NULL) 24969990Sdes err(1, "calloc"); 25069990Sdes x->x_path = inpath; 25169990Sdes x->x_fp = infp; 25273891Sdes 25373891Sdes load(x); 25469990Sdes parse(x); 25569990Sdes if (Vflag) { 25669990Sdes if (signature_size(x) == 0) 25769990Sdes errx(1, "file not signed"); 25871721Sdes 25971721Sdes printf("file contains signature\n"); 26071721Sdes if (vflag) { 26171721Sdes digest(x); 26271721Sdes show_digest(x); 26371721Sdes show_certificate(x); 26471721Sdes } 26571721Sdes } else { 26671721Sdes if (signature_size(x) != 0) 26769990Sdes errx(1, "file already signed"); 26869990Sdes 26971721Sdes digest(x); 27069990Sdes if (vflag) 27169990Sdes show_digest(x); 27269990Sdes send_digest(x, pipefd); 27369990Sdes receive_signature(x, pipefd); 27469990Sdes update(x); 27573891Sdes save(x, outfp, outpath); 27671721Sdes } 27769990Sdes 27869990Sdes return (0); 27969990Sdes} 28069990Sdes