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 #include <string.h> 36 37 #include <openssl/err.h> 38 #include <openssl/ssl.h> 39 40 #include "pkg.h" 41 42 #include "config.h" 43 #include "hash.h" 44 45 static EVP_PKEY * 46 load_public_key_file(const char *file) 47 { 48 EVP_PKEY *pkey; 49 BIO *bp; 50 char errbuf[1024]; 51 52 bp = BIO_new_file(file, "r"); 53 if (!bp) 54 errx(EXIT_FAILURE, "Unable to read %s", file); 55 56 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 57 warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 58 59 BIO_free(bp); 60 61 return (pkey); 62 } 63 64 static EVP_PKEY * 65 load_public_key_buf(const unsigned char *cert, int certlen) 66 { 67 EVP_PKEY *pkey; 68 BIO *bp; 69 char errbuf[1024]; 70 71 bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 72 73 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 74 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 75 76 BIO_free(bp); 77 78 return (pkey); 79 } 80 81 static bool 82 rsa_verify_data(const struct pkgsign_ctx *ctx __unused, 83 const char *data, size_t datasz, const char *sigfile, 84 const unsigned char *key, int keylen, unsigned char *sig, int siglen) 85 { 86 EVP_MD_CTX *mdctx; 87 EVP_PKEY *pkey; 88 char errbuf[1024]; 89 bool ret; 90 91 pkey = NULL; 92 mdctx = NULL; 93 ret = false; 94 SSL_load_error_strings(); 95 96 if (sigfile != NULL) { 97 if ((pkey = load_public_key_file(sigfile)) == NULL) { 98 warnx("Error reading public key"); 99 goto cleanup; 100 } 101 } else { 102 if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 103 warnx("Error reading public key"); 104 goto cleanup; 105 } 106 } 107 108 /* Verify signature of the SHA256(pkg) is valid. */ 109 if ((mdctx = EVP_MD_CTX_create()) == NULL) { 110 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 111 goto error; 112 } 113 114 if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 115 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 116 goto error; 117 } 118 if (EVP_DigestVerifyUpdate(mdctx, data, datasz) != 1) { 119 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 120 goto error; 121 } 122 123 if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 124 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 125 goto error; 126 } 127 128 ret = true; 129 printf("done\n"); 130 goto cleanup; 131 132 error: 133 printf("failed\n"); 134 135 cleanup: 136 if (pkey) 137 EVP_PKEY_free(pkey); 138 if (mdctx) 139 EVP_MD_CTX_destroy(mdctx); 140 ERR_free_strings(); 141 142 return (ret); 143 } 144 145 static bool 146 rsa_verify_cert(const struct pkgsign_ctx *ctx __unused, int fd, 147 const char *sigfile, const unsigned char *key, int keylen, 148 unsigned char *sig, int siglen) 149 { 150 char *sha256; 151 bool ret; 152 153 sha256 = NULL; 154 155 /* Compute SHA256 of the package. */ 156 if (lseek(fd, 0, 0) == -1) { 157 warn("lseek"); 158 return (false); 159 } 160 if ((sha256 = sha256_fd(fd)) == NULL) { 161 warnx("Error creating SHA256 hash for package"); 162 return (false); 163 } 164 165 ret = rsa_verify_data(ctx, sha256, strlen(sha256), sigfile, key, keylen, 166 sig, siglen); 167 free(sha256); 168 169 return (ret); 170 } 171 172 const struct pkgsign_ops pkgsign_rsa = { 173 .pkgsign_verify_cert = rsa_verify_cert, 174 .pkgsign_verify_data = rsa_verify_data, 175 }; 176