1 /* $OpenBSD: tls_conninfo.c,v 1.22 2021/01/05 15:57:38 tb 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
tls_hex_string(const unsigned char * in,size_t inlen,char ** out,size_t * outlen)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
tls_get_peer_cert_hash(struct tls * ctx,char ** hash)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
tls_get_peer_cert_issuer(struct tls * ctx,char ** issuer)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
tls_get_peer_cert_subject(struct tls * ctx,char ** subject)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
tls_get_peer_cert_times(struct tls * ctx,time_t * notbefore,time_t * notafter)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 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
116 goto err;
117 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
118 goto err;
119 if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1)
120 goto err;
121 if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1)
122 goto err;
123 if (!ASN1_time_tm_clamp_notafter(&after_tm))
124 goto err;
125 if ((*notbefore = timegm(&before_tm)) == -1)
126 goto err;
127 if ((*notafter = timegm(&after_tm)) == -1)
128 goto err;
129
130 return (0);
131
132 err:
133 return (-1);
134 }
135
136 static int
tls_get_peer_cert_info(struct tls * ctx)137 tls_get_peer_cert_info(struct tls *ctx)
138 {
139 if (ctx->ssl_peer_cert == NULL)
140 return (0);
141
142 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
143 goto err;
144 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1)
145 goto err;
146 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
147 goto err;
148 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
149 &ctx->conninfo->notafter) == -1)
150 goto err;
151
152 return (0);
153
154 err:
155 return (-1);
156 }
157
158 static int
tls_conninfo_alpn_proto(struct tls * ctx)159 tls_conninfo_alpn_proto(struct tls *ctx)
160 {
161 const unsigned char *p;
162 unsigned int len;
163
164 free(ctx->conninfo->alpn);
165 ctx->conninfo->alpn = NULL;
166
167 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len);
168 if (len > 0) {
169 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL)
170 return (-1);
171 memcpy(ctx->conninfo->alpn, p, len);
172 ctx->conninfo->alpn[len] = '\0';
173 }
174
175 return (0);
176 }
177
178 static int
tls_conninfo_cert_pem(struct tls * ctx)179 tls_conninfo_cert_pem(struct tls *ctx)
180 {
181 int i, rv = -1;
182 BIO *membio = NULL;
183 BUF_MEM *bptr = NULL;
184
185 if (ctx->ssl_peer_cert == NULL)
186 return 0;
187 if ((membio = BIO_new(BIO_s_mem()))== NULL)
188 goto err;
189
190 /*
191 * We have to write the peer cert out separately, because
192 * the certificate chain may or may not contain it.
193 */
194 if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert))
195 goto err;
196 for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) {
197 X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i);
198 if (chaincert != ctx->ssl_peer_cert &&
199 !PEM_write_bio_X509(membio, chaincert))
200 goto err;
201 }
202
203 BIO_get_mem_ptr(membio, &bptr);
204 free(ctx->conninfo->peer_cert);
205 ctx->conninfo->peer_cert_len = 0;
206 if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL)
207 goto err;
208 ctx->conninfo->peer_cert_len = bptr->length;
209 memcpy(ctx->conninfo->peer_cert, bptr->data,
210 ctx->conninfo->peer_cert_len);
211
212 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */
213 rv = 0;
214 err:
215 BIO_free(membio);
216 return rv;
217 }
218
219 static int
tls_conninfo_session(struct tls * ctx)220 tls_conninfo_session(struct tls *ctx)
221 {
222 ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn);
223
224 return 0;
225 }
226
227 int
tls_conninfo_populate(struct tls * ctx)228 tls_conninfo_populate(struct tls *ctx)
229 {
230 const char *tmp;
231
232 tls_conninfo_free(ctx->conninfo);
233
234 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) {
235 tls_set_errorx(ctx, "out of memory");
236 goto err;
237 }
238
239 if (tls_conninfo_alpn_proto(ctx) == -1)
240 goto err;
241
242 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
243 goto err;
244 if ((ctx->conninfo->cipher = strdup(tmp)) == NULL)
245 goto err;
246 ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL);
247
248 if (ctx->servername != NULL) {
249 if ((ctx->conninfo->servername =
250 strdup(ctx->servername)) == NULL)
251 goto err;
252 }
253
254 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
255 goto err;
256 if ((ctx->conninfo->version = strdup(tmp)) == NULL)
257 goto err;
258
259 if (tls_get_peer_cert_info(ctx) == -1)
260 goto err;
261
262 if (tls_conninfo_cert_pem(ctx) == -1)
263 goto err;
264
265 if (tls_conninfo_session(ctx) == -1)
266 goto err;
267
268 return (0);
269
270 err:
271 tls_conninfo_free(ctx->conninfo);
272 ctx->conninfo = NULL;
273
274 return (-1);
275 }
276
277 void
tls_conninfo_free(struct tls_conninfo * conninfo)278 tls_conninfo_free(struct tls_conninfo *conninfo)
279 {
280 if (conninfo == NULL)
281 return;
282
283 free(conninfo->alpn);
284 free(conninfo->cipher);
285 free(conninfo->servername);
286 free(conninfo->version);
287
288 free(conninfo->hash);
289 free(conninfo->issuer);
290 free(conninfo->subject);
291
292 free(conninfo->peer_cert);
293
294 free(conninfo);
295 }
296
297 const char *
tls_conn_alpn_selected(struct tls * ctx)298 tls_conn_alpn_selected(struct tls *ctx)
299 {
300 if (ctx->conninfo == NULL)
301 return (NULL);
302 return (ctx->conninfo->alpn);
303 }
304
305 const char *
tls_conn_cipher(struct tls * ctx)306 tls_conn_cipher(struct tls *ctx)
307 {
308 if (ctx->conninfo == NULL)
309 return (NULL);
310 return (ctx->conninfo->cipher);
311 }
312
313 int
tls_conn_cipher_strength(struct tls * ctx)314 tls_conn_cipher_strength(struct tls *ctx)
315 {
316 if (ctx->conninfo == NULL)
317 return (0);
318 return (ctx->conninfo->cipher_strength);
319 }
320
321 const char *
tls_conn_servername(struct tls * ctx)322 tls_conn_servername(struct tls *ctx)
323 {
324 if (ctx->conninfo == NULL)
325 return (NULL);
326 return (ctx->conninfo->servername);
327 }
328
329 int
tls_conn_session_resumed(struct tls * ctx)330 tls_conn_session_resumed(struct tls *ctx)
331 {
332 if (ctx->conninfo == NULL)
333 return (0);
334 return (ctx->conninfo->session_resumed);
335 }
336
337 const char *
tls_conn_version(struct tls * ctx)338 tls_conn_version(struct tls *ctx)
339 {
340 if (ctx->conninfo == NULL)
341 return (NULL);
342 return (ctx->conninfo->version);
343 }
344