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