1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org> 5 * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 33 #include <err.h> 34 #include <stdbool.h> 35 36 #include <openssl/err.h> 37 #include <openssl/ssl.h> 38 39 #include "pkg.h" 40 41 #include "config.h" 42 #include "hash.h" 43 44 static EVP_PKEY * 45 load_public_key_file(const char *file) 46 { 47 EVP_PKEY *pkey; 48 BIO *bp; 49 char errbuf[1024]; 50 51 bp = BIO_new_file(file, "r"); 52 if (!bp) 53 errx(EXIT_FAILURE, "Unable to read %s", file); 54 55 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 56 warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 57 58 BIO_free(bp); 59 60 return (pkey); 61 } 62 63 static EVP_PKEY * 64 load_public_key_buf(const unsigned char *cert, int certlen) 65 { 66 EVP_PKEY *pkey; 67 BIO *bp; 68 char errbuf[1024]; 69 70 bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 71 72 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 73 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 74 75 BIO_free(bp); 76 77 return (pkey); 78 } 79 80 static bool 81 rsa_verify_data(const struct pkgsign_ctx *ctx __unused, 82 const char *data, size_t datasz, const char *sigfile, 83 const unsigned char *key, int keylen, unsigned char *sig, int siglen) 84 { 85 EVP_MD_CTX *mdctx; 86 EVP_PKEY *pkey; 87 char errbuf[1024]; 88 bool ret; 89 90 pkey = NULL; 91 mdctx = NULL; 92 ret = false; 93 SSL_load_error_strings(); 94 95 if (sigfile != NULL) { 96 if ((pkey = load_public_key_file(sigfile)) == NULL) { 97 warnx("Error reading public key"); 98 goto cleanup; 99 } 100 } else { 101 if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 102 warnx("Error reading public key"); 103 goto cleanup; 104 } 105 } 106 107 /* Verify signature of the SHA256(pkg) is valid. */ 108 if ((mdctx = EVP_MD_CTX_create()) == NULL) { 109 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 110 goto error; 111 } 112 113 if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 114 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 115 goto error; 116 } 117 if (EVP_DigestVerifyUpdate(mdctx, data, datasz) != 1) { 118 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 119 goto error; 120 } 121 122 if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 123 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 124 goto error; 125 } 126 127 ret = true; 128 printf("done\n"); 129 goto cleanup; 130 131 error: 132 printf("failed\n"); 133 134 cleanup: 135 if (pkey) 136 EVP_PKEY_free(pkey); 137 if (mdctx) 138 EVP_MD_CTX_destroy(mdctx); 139 ERR_free_strings(); 140 141 return (ret); 142 } 143 144 static bool 145 rsa_verify_cert(const struct pkgsign_ctx *ctx __unused, int fd, 146 const char *sigfile, const unsigned char *key, int keylen, 147 unsigned char *sig, int siglen) 148 { 149 char *sha256; 150 bool ret; 151 152 sha256 = NULL; 153 154 /* Compute SHA256 of the package. */ 155 if (lseek(fd, 0, 0) == -1) { 156 warn("lseek"); 157 return (false); 158 } 159 if ((sha256 = sha256_fd(fd)) == NULL) { 160 warnx("Error creating SHA256 hash for package"); 161 return (false); 162 } 163 164 ret = rsa_verify_data(ctx, sha256, strlen(sha256), sigfile, key, keylen, 165 sig, siglen); 166 free(sha256); 167 168 return (ret); 169 } 170 171 const struct pkgsign_ops pkgsign_rsa = { 172 .pkgsign_verify_cert = rsa_verify_cert, 173 .pkgsign_verify_data = rsa_verify_data, 174 }; 175