1 /* $OpenBSD: ssl.c,v 1.96 2021/06/14 17:58:16 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/stat.h> 22 23 #include <fcntl.h> 24 #include <limits.h> 25 #include <openssl/engine.h> 26 #include <openssl/err.h> 27 #include <openssl/ssl.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "log.h" 32 #include "ssl.h" 33 34 void 35 ssl_init(void) 36 { 37 static int inited = 0; 38 39 if (inited) 40 return; 41 42 SSL_library_init(); 43 SSL_load_error_strings(); 44 45 OpenSSL_add_all_algorithms(); 46 47 /* Init hardware crypto engines. */ 48 ENGINE_load_builtin_engines(); 49 ENGINE_register_all_complete(); 50 inited = 1; 51 } 52 53 static char * 54 ssl_load_file(const char *name, off_t *len, mode_t perm) 55 { 56 struct stat st; 57 off_t size; 58 char *buf = NULL; 59 int fd, saved_errno; 60 char mode[12]; 61 62 if ((fd = open(name, O_RDONLY)) == -1) 63 return (NULL); 64 if (fstat(fd, &st) != 0) 65 goto fail; 66 if (st.st_uid != 0) { 67 log_warnx("warn: %s: not owned by uid 0", name); 68 errno = EACCES; 69 goto fail; 70 } 71 if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) { 72 strmode(perm, mode); 73 log_warnx("warn: %s: insecure permissions: must be at most %s", 74 name, &mode[1]); 75 errno = EACCES; 76 goto fail; 77 } 78 size = st.st_size; 79 if ((buf = calloc(1, size + 1)) == NULL) 80 goto fail; 81 if (read(fd, buf, size) != size) 82 goto fail; 83 close(fd); 84 85 *len = size + 1; 86 return (buf); 87 88 fail: 89 free(buf); 90 saved_errno = errno; 91 close(fd); 92 errno = saved_errno; 93 return (NULL); 94 } 95 96 #if 0 97 static int 98 ssl_password_cb(char *buf, int size, int rwflag, void *u) 99 { 100 size_t len; 101 if (u == NULL) { 102 explicit_bzero(buf, size); 103 return (0); 104 } 105 if ((len = strlcpy(buf, u, size)) >= (size_t)size) 106 return (0); 107 return (len); 108 } 109 #endif 110 111 static int 112 ssl_password_cb(char *buf, int size, int rwflag, void *u) 113 { 114 int ret = 0; 115 size_t len; 116 char *pass; 117 118 pass = getpass((const char *)u); 119 if (pass == NULL) 120 return 0; 121 len = strlen(pass); 122 if (strlcpy(buf, pass, size) >= (size_t)size) 123 goto end; 124 ret = len; 125 end: 126 if (len) 127 explicit_bzero(pass, len); 128 return ret; 129 } 130 131 static char * 132 ssl_load_key(const char *name, off_t *len, char *pass, mode_t perm, const char *pkiname) 133 { 134 FILE *fp = NULL; 135 EVP_PKEY *key = NULL; 136 BIO *bio = NULL; 137 long size; 138 char *data, *buf, *filebuf; 139 struct stat st; 140 char mode[12]; 141 char prompt[2048]; 142 143 /* Initialize SSL library once */ 144 ssl_init(); 145 146 /* 147 * Read (possibly) encrypted key from file 148 */ 149 if ((fp = fopen(name, "r")) == NULL) 150 return (NULL); 151 if ((filebuf = malloc_conceal(BUFSIZ)) == NULL) 152 goto fail; 153 setvbuf(fp, filebuf, _IOFBF, BUFSIZ); 154 155 if (fstat(fileno(fp), &st) != 0) 156 goto fail; 157 if (st.st_uid != 0) { 158 log_warnx("warn: %s: not owned by uid 0", name); 159 errno = EACCES; 160 goto fail; 161 } 162 if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) { 163 strmode(perm, mode); 164 log_warnx("warn: %s: insecure permissions: must be at most %s", 165 name, &mode[1]); 166 errno = EACCES; 167 goto fail; 168 } 169 170 (void)snprintf(prompt, sizeof prompt, "passphrase for %s: ", pkiname); 171 key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, prompt); 172 fclose(fp); 173 fp = NULL; 174 freezero(filebuf, BUFSIZ); 175 filebuf = NULL; 176 if (key == NULL) 177 goto fail; 178 /* 179 * Write unencrypted key to memory buffer 180 */ 181 if ((bio = BIO_new(BIO_s_mem())) == NULL) 182 goto fail; 183 if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) 184 goto fail; 185 if ((size = BIO_get_mem_data(bio, &data)) <= 0) 186 goto fail; 187 if ((buf = calloc_conceal(1, size + 1)) == NULL) 188 goto fail; 189 memcpy(buf, data, size); 190 191 BIO_free_all(bio); 192 EVP_PKEY_free(key); 193 194 *len = (off_t)size + 1; 195 return (buf); 196 197 fail: 198 ssl_error("ssl_load_key"); 199 BIO_free_all(bio); 200 EVP_PKEY_free(key); 201 if (fp) 202 fclose(fp); 203 freezero(filebuf, BUFSIZ); 204 return (NULL); 205 } 206 207 int 208 ssl_load_certificate(struct pki *p, const char *pathname) 209 { 210 p->pki_cert = ssl_load_file(pathname, &p->pki_cert_len, 0755); 211 if (p->pki_cert == NULL) 212 return 0; 213 return 1; 214 } 215 216 int 217 ssl_load_keyfile(struct pki *p, const char *pathname, const char *pkiname) 218 { 219 char pass[1024]; 220 221 p->pki_key = ssl_load_key(pathname, &p->pki_key_len, pass, 0740, pkiname); 222 if (p->pki_key == NULL) 223 return 0; 224 return 1; 225 } 226 227 int 228 ssl_load_cafile(struct ca *c, const char *pathname) 229 { 230 c->ca_cert = ssl_load_file(pathname, &c->ca_cert_len, 0755); 231 if (c->ca_cert == NULL) 232 return 0; 233 return 1; 234 } 235 236 void 237 ssl_error(const char *where) 238 { 239 unsigned long code; 240 char errbuf[128]; 241 242 for (; (code = ERR_get_error()) != 0 ;) { 243 ERR_error_string_n(code, errbuf, sizeof(errbuf)); 244 log_debug("debug: SSL library error: %s: %s", where, errbuf); 245 } 246 } 247 248 static void 249 hash_x509(X509 *cert, char *hash, size_t hashlen) 250 { 251 static const char hex[] = "0123456789abcdef"; 252 size_t off; 253 char digest[EVP_MAX_MD_SIZE]; 254 int dlen, i; 255 256 if (X509_pubkey_digest(cert, EVP_sha256(), digest, &dlen) != 1) 257 fatalx("%s: X509_pubkey_digest failed", __func__); 258 259 if (hashlen < 2 * dlen + sizeof("SHA256:")) 260 fatalx("%s: hash buffer to small", __func__); 261 262 off = strlcpy(hash, "SHA256:", hashlen); 263 264 for (i = 0; i < dlen; i++) { 265 hash[off++] = hex[(digest[i] >> 4) & 0x0f]; 266 hash[off++] = hex[digest[i] & 0x0f]; 267 } 268 hash[off] = 0; 269 } 270 271 char * 272 ssl_pubkey_hash(const char *buf, off_t len) 273 { 274 #define TLS_CERT_HASH_SIZE 128 275 BIO *in; 276 X509 *x509 = NULL; 277 char *hash = NULL; 278 279 if ((in = BIO_new_mem_buf(buf, len)) == NULL) { 280 log_warnx("%s: BIO_new_mem_buf failed", __func__); 281 return NULL; 282 } 283 284 if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) { 285 log_warnx("%s: PEM_read_bio_X509 failed", __func__); 286 goto fail; 287 } 288 289 if ((hash = malloc(TLS_CERT_HASH_SIZE)) == NULL) { 290 log_warn("%s: malloc", __func__); 291 goto fail; 292 } 293 hash_x509(x509, hash, TLS_CERT_HASH_SIZE); 294 295 fail: 296 BIO_free(in); 297 298 if (x509) 299 X509_free(x509); 300 301 return hash; 302 } 303