1 /* $OpenBSD: ssl.c,v 1.95 2021/05/26 07:05:50 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org> 6 * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/queue.h> 23 #include <sys/tree.h> 24 #include <sys/socket.h> 25 #include <sys/stat.h> 26 27 #include <ctype.h> 28 #include <event.h> 29 #include <fcntl.h> 30 #include <imsg.h> 31 #include <limits.h> 32 #include <pwd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include <openssl/ssl.h> 39 #include <openssl/engine.h> 40 #include <openssl/err.h> 41 #include <openssl/rsa.h> 42 #include <openssl/ecdsa.h> 43 #include <openssl/dh.h> 44 #include <openssl/bn.h> 45 46 #include "log.h" 47 #include "ssl.h" 48 49 void 50 ssl_init(void) 51 { 52 static int inited = 0; 53 54 if (inited) 55 return; 56 57 SSL_library_init(); 58 SSL_load_error_strings(); 59 60 OpenSSL_add_all_algorithms(); 61 62 /* Init hardware crypto engines. */ 63 ENGINE_load_builtin_engines(); 64 ENGINE_register_all_complete(); 65 inited = 1; 66 } 67 68 static char * 69 ssl_load_file(const char *name, off_t *len, mode_t perm) 70 { 71 struct stat st; 72 off_t size; 73 char *buf = NULL; 74 int fd, saved_errno; 75 char mode[12]; 76 77 if ((fd = open(name, O_RDONLY)) == -1) 78 return (NULL); 79 if (fstat(fd, &st) != 0) 80 goto fail; 81 if (st.st_uid != 0) { 82 log_warnx("warn: %s: not owned by uid 0", name); 83 errno = EACCES; 84 goto fail; 85 } 86 if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) { 87 strmode(perm, mode); 88 log_warnx("warn: %s: insecure permissions: must be at most %s", 89 name, &mode[1]); 90 errno = EACCES; 91 goto fail; 92 } 93 size = st.st_size; 94 if ((buf = calloc(1, size + 1)) == NULL) 95 goto fail; 96 if (read(fd, buf, size) != size) 97 goto fail; 98 close(fd); 99 100 *len = size + 1; 101 return (buf); 102 103 fail: 104 free(buf); 105 saved_errno = errno; 106 close(fd); 107 errno = saved_errno; 108 return (NULL); 109 } 110 111 #if 0 112 static int 113 ssl_password_cb(char *buf, int size, int rwflag, void *u) 114 { 115 size_t len; 116 if (u == NULL) { 117 explicit_bzero(buf, size); 118 return (0); 119 } 120 if ((len = strlcpy(buf, u, size)) >= (size_t)size) 121 return (0); 122 return (len); 123 } 124 #endif 125 126 static int 127 ssl_password_cb(char *buf, int size, int rwflag, void *u) 128 { 129 int ret = 0; 130 size_t len; 131 char *pass; 132 133 pass = getpass((const char *)u); 134 if (pass == NULL) 135 return 0; 136 len = strlen(pass); 137 if (strlcpy(buf, pass, size) >= (size_t)size) 138 goto end; 139 ret = len; 140 end: 141 if (len) 142 explicit_bzero(pass, len); 143 return ret; 144 } 145 146 static char * 147 ssl_load_key(const char *name, off_t *len, char *pass, mode_t perm, const char *pkiname) 148 { 149 FILE *fp = NULL; 150 EVP_PKEY *key = NULL; 151 BIO *bio = NULL; 152 long size; 153 char *data, *buf, *filebuf; 154 struct stat st; 155 char mode[12]; 156 char prompt[2048]; 157 158 /* Initialize SSL library once */ 159 ssl_init(); 160 161 /* 162 * Read (possibly) encrypted key from file 163 */ 164 if ((fp = fopen(name, "r")) == NULL) 165 return (NULL); 166 if ((filebuf = malloc_conceal(BUFSIZ)) == NULL) 167 goto fail; 168 setvbuf(fp, filebuf, _IOFBF, BUFSIZ); 169 170 if (fstat(fileno(fp), &st) != 0) 171 goto fail; 172 if (st.st_uid != 0) { 173 log_warnx("warn: %s: not owned by uid 0", name); 174 errno = EACCES; 175 goto fail; 176 } 177 if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) { 178 strmode(perm, mode); 179 log_warnx("warn: %s: insecure permissions: must be at most %s", 180 name, &mode[1]); 181 errno = EACCES; 182 goto fail; 183 } 184 185 (void)snprintf(prompt, sizeof prompt, "passphrase for %s: ", pkiname); 186 key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, prompt); 187 fclose(fp); 188 fp = NULL; 189 freezero(filebuf, BUFSIZ); 190 filebuf = NULL; 191 if (key == NULL) 192 goto fail; 193 /* 194 * Write unencrypted key to memory buffer 195 */ 196 if ((bio = BIO_new(BIO_s_mem())) == NULL) 197 goto fail; 198 if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) 199 goto fail; 200 if ((size = BIO_get_mem_data(bio, &data)) <= 0) 201 goto fail; 202 if ((buf = calloc_conceal(1, size + 1)) == NULL) 203 goto fail; 204 memcpy(buf, data, size); 205 206 BIO_free_all(bio); 207 EVP_PKEY_free(key); 208 209 *len = (off_t)size + 1; 210 return (buf); 211 212 fail: 213 ssl_error("ssl_load_key"); 214 BIO_free_all(bio); 215 EVP_PKEY_free(key); 216 if (fp) 217 fclose(fp); 218 freezero(filebuf, BUFSIZ); 219 return (NULL); 220 } 221 222 int 223 ssl_load_certificate(struct pki *p, const char *pathname) 224 { 225 p->pki_cert = ssl_load_file(pathname, &p->pki_cert_len, 0755); 226 if (p->pki_cert == NULL) 227 return 0; 228 return 1; 229 } 230 231 int 232 ssl_load_keyfile(struct pki *p, const char *pathname, const char *pkiname) 233 { 234 char pass[1024]; 235 236 p->pki_key = ssl_load_key(pathname, &p->pki_key_len, pass, 0740, pkiname); 237 if (p->pki_key == NULL) 238 return 0; 239 return 1; 240 } 241 242 int 243 ssl_load_cafile(struct ca *c, const char *pathname) 244 { 245 c->ca_cert = ssl_load_file(pathname, &c->ca_cert_len, 0755); 246 if (c->ca_cert == NULL) 247 return 0; 248 return 1; 249 } 250 251 void 252 ssl_error(const char *where) 253 { 254 unsigned long code; 255 char errbuf[128]; 256 257 for (; (code = ERR_get_error()) != 0 ;) { 258 ERR_error_string_n(code, errbuf, sizeof(errbuf)); 259 log_debug("debug: SSL library error: %s: %s", where, errbuf); 260 } 261 } 262 263 static void 264 hash_x509(X509 *cert, char *hash, size_t hashlen) 265 { 266 static const char hex[] = "0123456789abcdef"; 267 size_t off; 268 char digest[EVP_MAX_MD_SIZE]; 269 int dlen, i; 270 271 if (X509_pubkey_digest(cert, EVP_sha256(), digest, &dlen) != 1) 272 fatalx("%s: X509_pubkey_digest failed", __func__); 273 274 if (hashlen < 2 * dlen + sizeof("SHA256:")) 275 fatalx("%s: hash buffer to small", __func__); 276 277 off = strlcpy(hash, "SHA256:", hashlen); 278 279 for (i = 0; i < dlen; i++) { 280 hash[off++] = hex[(digest[i] >> 4) & 0x0f]; 281 hash[off++] = hex[digest[i] & 0x0f]; 282 } 283 hash[off] = 0; 284 } 285 286 char * 287 ssl_pubkey_hash(const char *buf, off_t len) 288 { 289 #define TLS_CERT_HASH_SIZE 128 290 BIO *in; 291 X509 *x509 = NULL; 292 char *hash = NULL; 293 294 if ((in = BIO_new_mem_buf(buf, len)) == NULL) { 295 log_warnx("%s: BIO_new_mem_buf failed", __func__); 296 return NULL; 297 } 298 299 if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) { 300 log_warnx("%s: PEM_read_bio_X509 failed", __func__); 301 goto fail; 302 } 303 304 if ((hash = malloc(TLS_CERT_HASH_SIZE)) == NULL) { 305 log_warn("%s: malloc", __func__); 306 goto fail; 307 } 308 hash_x509(x509, hash, TLS_CERT_HASH_SIZE); 309 310 fail: 311 BIO_free(in); 312 313 if (x509) 314 X509_free(x509); 315 316 return hash; 317 } 318