xref: /dragonfly/crypto/libressl/tls/tls_conninfo.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
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