GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libtls/tls_util.c Lines: 15 62 24.2 %
Date: 2017-11-07 Branches: 7 48 14.6 %

Line Branch Exec Source
1
/* $OpenBSD: tls_util.c,v 1.9 2017/06/22 18:03:57 jsing Exp $ */
2
/*
3
 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4
 * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/stat.h>
20
21
#include <stdlib.h>
22
#include <unistd.h>
23
#include <fcntl.h>
24
25
#include "tls.h"
26
#include "tls_internal.h"
27
28
/*
29
 * Extract the host and port from a colon separated value. For a literal IPv6
30
 * address the address must be contained with square braces. If a host and
31
 * port are successfully extracted, the function will return 0 and the
32
 * caller is responsible for freeing the host and port. If no port is found
33
 * then the function will return 1, with both host and port being NULL.
34
 * On memory allocation failure -1 will be returned.
35
 */
36
int
37
tls_host_port(const char *hostport, char **host, char **port)
38
{
39
	char *h, *p, *s;
40
	int rv = 1;
41
42
	*host = NULL;
43
	*port = NULL;
44
45
	if ((s = strdup(hostport)) == NULL)
46
		goto fail;
47
48
	h = p = s;
49
50
	/* See if this is an IPv6 literal with square braces. */
51
	if (p[0] == '[') {
52
		h++;
53
		if ((p = strchr(s, ']')) == NULL)
54
			goto done;
55
		*p++ = '\0';
56
	}
57
58
	/* Find the port seperator. */
59
	if ((p = strchr(p, ':')) == NULL)
60
		goto done;
61
62
	/* If there is another separator then we have issues. */
63
	if (strchr(p + 1, ':') != NULL)
64
		goto done;
65
66
	*p++ = '\0';
67
68
	if (asprintf(host, "%s", h) == -1)
69
		goto fail;
70
	if (asprintf(port, "%s", p) == -1)
71
		goto fail;
72
73
	rv = 0;
74
	goto done;
75
76
 fail:
77
	free(*host);
78
	*host = NULL;
79
	free(*port);
80
	*port = NULL;
81
	rv = -1;
82
83
 done:
84
	free(s);
85
86
	return (rv);
87
}
88
89
int
90
tls_password_cb(char *buf, int size, int rwflag, void *u)
91
{
92
	size_t len;
93
94
	if (size < 0)
95
		return (0);
96
97
	if (u == NULL) {
98
		memset(buf, 0, size);
99
		return (0);
100
	}
101
102
	if ((len = strlcpy(buf, u, size)) >= (size_t)size)
103
		return (0);
104
105
	return (len);
106
}
107
108
uint8_t *
109
tls_load_file(const char *name, size_t *len, char *password)
110
{
111
	FILE *fp;
112
	EVP_PKEY *key = NULL;
113
	BIO *bio = NULL;
114
32
	char *data;
115
	uint8_t *buf = NULL;
116
16
	struct stat st;
117
	size_t size = 0;
118
	int fd = -1;
119
	ssize_t n;
120
121
16
	*len = 0;
122
123
16
	if ((fd = open(name, O_RDONLY)) == -1)
124
		return (NULL);
125
126
	/* Just load the file into memory without decryption */
127
16
	if (password == NULL) {
128
16
		if (fstat(fd, &st) != 0)
129
			goto fail;
130
16
		if (st.st_size < 0)
131
			goto fail;
132
		size = (size_t)st.st_size;
133
16
		if ((buf = malloc(size)) == NULL)
134
			goto fail;
135
16
		n = read(fd, buf, size);
136

32
		if (n < 0 || (size_t)n != size)
137
			goto fail;
138
16
		close(fd);
139
16
		goto done;
140
	}
141
142
	/* Or read the (possibly) encrypted key from file */
143
	if ((fp = fdopen(fd, "r")) == NULL)
144
		goto fail;
145
	fd = -1;
146
147
	key = PEM_read_PrivateKey(fp, NULL, tls_password_cb, password);
148
	fclose(fp);
149
	if (key == NULL)
150
		goto fail;
151
152
	/* Write unencrypted key to memory buffer */
153
	if ((bio = BIO_new(BIO_s_mem())) == NULL)
154
		goto fail;
155
	if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL))
156
		goto fail;
157
	if ((size = BIO_get_mem_data(bio, &data)) <= 0)
158
		goto fail;
159
	if ((buf = malloc(size)) == NULL)
160
		goto fail;
161
	memcpy(buf, data, size);
162
163
	BIO_free_all(bio);
164
	EVP_PKEY_free(key);
165
166
 done:
167
16
	*len = size;
168
16
	return (buf);
169
170
 fail:
171
	if (fd != -1)
172
		close(fd);
173
	freezero(buf, size);
174
	BIO_free_all(bio);
175
	EVP_PKEY_free(key);
176
177
	return (NULL);
178
16
}
179
180
void
181
tls_unload_file(uint8_t *buf, size_t len)
182
{
183
	freezero(buf, len);
184
}