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