1 /* $OpenBSD: tls_conninfo.c,v 1.21 2019/11/02 13:37:59 jsing Exp $ */
2 /*
3  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4  * Copyright (c) 2015 Bob Beck <beck@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 <stdio.h>
20 
21 #include <openssl/x509.h>
22 
23 #include <tls.h>
24 #include "tls_internal.h"
25 
26 int ASN1_time_tm_clamp_notafter(struct tm *tm);
27 
28 int
29 tls_hex_string(const unsigned char *in, size_t inlen, char **out,
30     size_t *outlen)
31 {
32 	static const char hex[] = "0123456789abcdef";
33 	size_t i, len;
34 	char *p;
35 
36 	if (outlen != NULL)
37 		*outlen = 0;
38 
39 	if (inlen >= SIZE_MAX)
40 		return (-1);
41 	if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL)
42 		return (-1);
43 
44 	p = *out;
45 	len = 0;
46 	for (i = 0; i < inlen; i++) {
47 		p[len++] = hex[(in[i] >> 4) & 0x0f];
48 		p[len++] = hex[in[i] & 0x0f];
49 	}
50 	p[len++] = 0;
51 
52 	if (outlen != NULL)
53 		*outlen = len;
54 
55 	return (0);
56 }
57 
58 static int
59 tls_get_peer_cert_hash(struct tls *ctx, char **hash)
60 {
61 	*hash = NULL;
62 	if (ctx->ssl_peer_cert == NULL)
63 		return (0);
64 
65 	if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) {
66 		tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory");
67 		*hash = NULL;
68 		return -1;
69 	}
70 	return 0;
71 }
72 
73 static int
74 tls_get_peer_cert_issuer(struct tls *ctx,  char **issuer)
75 {
76 	X509_NAME *name = NULL;
77 
78 	*issuer = NULL;
79 	if (ctx->ssl_peer_cert == NULL)
80 		return (-1);
81 	if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL)
82 		return (-1);
83 	*issuer = X509_NAME_oneline(name, 0, 0);
84 	if (*issuer == NULL)
85 		return (-1);
86 	return (0);
87 }
88 
89 static int
90 tls_get_peer_cert_subject(struct tls *ctx, char **subject)
91 {
92 	X509_NAME *name = NULL;
93 
94 	*subject = NULL;
95 	if (ctx->ssl_peer_cert == NULL)
96 		return (-1);
97 	if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL)
98 		return (-1);
99 	*subject = X509_NAME_oneline(name, 0, 0);
100 	if (*subject == NULL)
101 		return (-1);
102 	return (0);
103 }
104 
105 static int
106 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
107     time_t *notafter)
108 {
109 	struct tm before_tm, after_tm;
110 	ASN1_TIME *before, *after;
111 
112 	if (ctx->ssl_peer_cert == NULL)
113 		return (-1);
114 
115 	memset(&before_tm, 0, sizeof(before_tm));
116 	memset(&after_tm, 0, sizeof(after_tm));
117 
118 	if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
119 		goto err;
120 	if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
121 		goto err;
122 	if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1)
123 		goto err;
124 	if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1)
125 		goto err;
126 	if (!ASN1_time_tm_clamp_notafter(&after_tm))
127 		goto err;
128 	if ((*notbefore = timegm(&before_tm)) == -1)
129 		goto err;
130 	if ((*notafter = timegm(&after_tm)) == -1)
131 		goto err;
132 
133 	return (0);
134 
135  err:
136 	return (-1);
137 }
138 
139 static int
140 tls_get_peer_cert_info(struct tls *ctx)
141 {
142 	if (ctx->ssl_peer_cert == NULL)
143 		return (0);
144 
145 	if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
146 		goto err;
147 	if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1)
148 		goto err;
149 	if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
150 		goto err;
151 	if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
152 	    &ctx->conninfo->notafter) == -1)
153 		goto err;
154 
155 	return (0);
156 
157  err:
158 	return (-1);
159 }
160 
161 static int
162 tls_conninfo_alpn_proto(struct tls *ctx)
163 {
164 	const unsigned char *p;
165 	unsigned int len;
166 
167 	free(ctx->conninfo->alpn);
168 	ctx->conninfo->alpn = NULL;
169 
170 	SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len);
171 	if (len > 0) {
172 		if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL)
173 			return (-1);
174 		memcpy(ctx->conninfo->alpn, p, len);
175 		ctx->conninfo->alpn[len] = '\0';
176 	}
177 
178 	return (0);
179 }
180 
181 static int
182 tls_conninfo_cert_pem(struct tls *ctx)
183 {
184 	int i, rv = -1;
185 	BIO *membio = NULL;
186 	BUF_MEM *bptr = NULL;
187 
188 	if (ctx->ssl_peer_cert == NULL)
189 		return 0;
190 	if ((membio = BIO_new(BIO_s_mem()))== NULL)
191 		goto err;
192 
193 	/*
194 	 * We have to write the peer cert out separately, because
195 	 * the certificate chain may or may not contain it.
196 	 */
197 	if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert))
198 		goto err;
199 	for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) {
200 		X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i);
201 		if (chaincert != ctx->ssl_peer_cert &&
202 		    !PEM_write_bio_X509(membio, chaincert))
203 			goto err;
204 	}
205 
206 	BIO_get_mem_ptr(membio, &bptr);
207 	free(ctx->conninfo->peer_cert);
208 	ctx->conninfo->peer_cert_len = 0;
209 	if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL)
210 		goto err;
211 	ctx->conninfo->peer_cert_len = bptr->length;
212 	memcpy(ctx->conninfo->peer_cert, bptr->data,
213 	    ctx->conninfo->peer_cert_len);
214 
215 	/* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */
216 	rv = 0;
217  err:
218 	BIO_free(membio);
219 	return rv;
220 }
221 
222 static int
223 tls_conninfo_session(struct tls *ctx)
224 {
225 	ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn);
226 
227 	return 0;
228 }
229 
230 int
231 tls_conninfo_populate(struct tls *ctx)
232 {
233 	const char *tmp;
234 
235 	tls_conninfo_free(ctx->conninfo);
236 
237 	if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) {
238 		tls_set_errorx(ctx, "out of memory");
239 		goto err;
240 	}
241 
242 	if (tls_conninfo_alpn_proto(ctx) == -1)
243 		goto err;
244 
245 	if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
246 		goto err;
247 	if ((ctx->conninfo->cipher = strdup(tmp)) == NULL)
248 		goto err;
249 	ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL);
250 
251 	if (ctx->servername != NULL) {
252 		if ((ctx->conninfo->servername =
253 		    strdup(ctx->servername)) == NULL)
254 			goto err;
255 	}
256 
257 	if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
258 		goto err;
259 	if ((ctx->conninfo->version = strdup(tmp)) == NULL)
260 		goto err;
261 
262 	if (tls_get_peer_cert_info(ctx) == -1)
263 		goto err;
264 
265 	if (tls_conninfo_cert_pem(ctx) == -1)
266 		goto err;
267 
268 	if (tls_conninfo_session(ctx) == -1)
269 		goto err;
270 
271 	return (0);
272 
273  err:
274 	tls_conninfo_free(ctx->conninfo);
275 	ctx->conninfo = NULL;
276 
277 	return (-1);
278 }
279 
280 void
281 tls_conninfo_free(struct tls_conninfo *conninfo)
282 {
283 	if (conninfo == NULL)
284 		return;
285 
286 	free(conninfo->alpn);
287 	free(conninfo->cipher);
288 	free(conninfo->servername);
289 	free(conninfo->version);
290 
291 	free(conninfo->hash);
292 	free(conninfo->issuer);
293 	free(conninfo->subject);
294 
295 	free(conninfo->peer_cert);
296 
297 	free(conninfo);
298 }
299 
300 const char *
301 tls_conn_alpn_selected(struct tls *ctx)
302 {
303 	if (ctx->conninfo == NULL)
304 		return (NULL);
305 	return (ctx->conninfo->alpn);
306 }
307 
308 const char *
309 tls_conn_cipher(struct tls *ctx)
310 {
311 	if (ctx->conninfo == NULL)
312 		return (NULL);
313 	return (ctx->conninfo->cipher);
314 }
315 
316 int
317 tls_conn_cipher_strength(struct tls *ctx)
318 {
319 	if (ctx->conninfo == NULL)
320 		return (0);
321 	return (ctx->conninfo->cipher_strength);
322 }
323 
324 const char *
325 tls_conn_servername(struct tls *ctx)
326 {
327 	if (ctx->conninfo == NULL)
328 		return (NULL);
329 	return (ctx->conninfo->servername);
330 }
331 
332 int
333 tls_conn_session_resumed(struct tls *ctx)
334 {
335 	if (ctx->conninfo == NULL)
336 		return (0);
337 	return (ctx->conninfo->session_resumed);
338 }
339 
340 const char *
341 tls_conn_version(struct tls *ctx)
342 {
343 	if (ctx->conninfo == NULL)
344 		return (NULL);
345 	return (ctx->conninfo->version);
346 }
347