1 /* $OpenBSD: tls_conninfo.c,v 1.20 2018/02/10 04:48:44 jsing Exp $ */
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
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.
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.
21 #include <openssl/x509.h>
24 #include "tls_internal.h"
26 int ASN1_time_tm_clamp_notafter(struct tm
*tm
);
29 tls_hex_string(const unsigned char *in
, size_t inlen
, char **out
,
32 static const char hex
[] = "0123456789abcdef";
39 if (inlen
>= SIZE_MAX
)
41 if ((*out
= reallocarray(NULL
, inlen
+ 1, 2)) == NULL
)
46 for (i
= 0; i
< inlen
; i
++) {
47 p
[len
++] = hex
[(in
[i
] >> 4) & 0x0f];
48 p
[len
++] = hex
[in
[i
] & 0x0f];
59 tls_get_peer_cert_hash(struct tls
*ctx
, char **hash
)
62 if (ctx
->ssl_peer_cert
== NULL
)
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");
74 tls_get_peer_cert_issuer(struct tls
*ctx
, char **issuer
)
76 X509_NAME
*name
= NULL
;
79 if (ctx
->ssl_peer_cert
== NULL
)
81 if ((name
= X509_get_issuer_name(ctx
->ssl_peer_cert
)) == NULL
)
83 *issuer
= X509_NAME_oneline(name
, 0, 0);
90 tls_get_peer_cert_subject(struct tls
*ctx
, char **subject
)
92 X509_NAME
*name
= NULL
;
95 if (ctx
->ssl_peer_cert
== NULL
)
97 if ((name
= X509_get_subject_name(ctx
->ssl_peer_cert
)) == NULL
)
99 *subject
= X509_NAME_oneline(name
, 0, 0);
100 if (*subject
== NULL
)
106 tls_get_peer_cert_times(struct tls
*ctx
, time_t *notbefore
,
109 struct tm before_tm
, after_tm
;
110 ASN1_TIME
*before
, *after
;
112 if (ctx
->ssl_peer_cert
== NULL
)
115 memset(&before_tm
, 0, sizeof(before_tm
));
116 memset(&after_tm
, 0, sizeof(after_tm
));
118 if ((before
= X509_get_notBefore(ctx
->ssl_peer_cert
)) == NULL
)
120 if ((after
= X509_get_notAfter(ctx
->ssl_peer_cert
)) == NULL
)
122 if (ASN1_time_parse(before
->data
, before
->length
, &before_tm
, 0) == -1)
124 if (ASN1_time_parse(after
->data
, after
->length
, &after_tm
, 0) == -1)
126 if (!ASN1_time_tm_clamp_notafter(&after_tm
))
128 if ((*notbefore
= timegm(&before_tm
)) == -1)
130 if ((*notafter
= timegm(&after_tm
)) == -1)
140 tls_get_peer_cert_info(struct tls
*ctx
)
142 if (ctx
->ssl_peer_cert
== NULL
)
145 if (tls_get_peer_cert_hash(ctx
, &ctx
->conninfo
->hash
) == -1)
147 if (tls_get_peer_cert_subject(ctx
, &ctx
->conninfo
->subject
) == -1)
149 if (tls_get_peer_cert_issuer(ctx
, &ctx
->conninfo
->issuer
) == -1)
151 if (tls_get_peer_cert_times(ctx
, &ctx
->conninfo
->notbefore
,
152 &ctx
->conninfo
->notafter
) == -1)
162 tls_conninfo_alpn_proto(struct tls
*ctx
)
164 const unsigned char *p
;
167 free(ctx
->conninfo
->alpn
);
168 ctx
->conninfo
->alpn
= NULL
;
170 SSL_get0_alpn_selected(ctx
->ssl_conn
, &p
, &len
);
172 if ((ctx
->conninfo
->alpn
= malloc(len
+ 1)) == NULL
)
174 memcpy(ctx
->conninfo
->alpn
, p
, len
);
175 ctx
->conninfo
->alpn
[len
] = '\0';
182 tls_conninfo_cert_pem(struct tls
*ctx
)
186 BUF_MEM
*bptr
= NULL
;
188 if (ctx
->ssl_peer_cert
== NULL
)
190 if ((membio
= BIO_new(BIO_s_mem()))== NULL
)
194 * We have to write the peer cert out separately, because
195 * the certificate chain may or may not contain it.
197 if (!PEM_write_bio_X509(membio
, ctx
->ssl_peer_cert
))
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
))
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
)
211 ctx
->conninfo
->peer_cert_len
= bptr
->length
;
212 memcpy(ctx
->conninfo
->peer_cert
, bptr
->data
,
213 ctx
->conninfo
->peer_cert_len
);
215 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */
223 tls_conninfo_session(struct tls
*ctx
)
225 ctx
->conninfo
->session_resumed
= SSL_session_reused(ctx
->ssl_conn
);
231 tls_conninfo_populate(struct tls
*ctx
)
235 tls_conninfo_free(ctx
->conninfo
);
237 if ((ctx
->conninfo
= calloc(1, sizeof(struct tls_conninfo
))) == NULL
) {
238 tls_set_errorx(ctx
, "out of memory");
242 if (tls_conninfo_alpn_proto(ctx
) == -1)
245 if ((tmp
= SSL_get_cipher(ctx
->ssl_conn
)) == NULL
)
247 if ((ctx
->conninfo
->cipher
= strdup(tmp
)) == NULL
)
250 if (ctx
->servername
!= NULL
) {
251 if ((ctx
->conninfo
->servername
=
252 strdup(ctx
->servername
)) == NULL
)
256 if ((tmp
= SSL_get_version(ctx
->ssl_conn
)) == NULL
)
258 if ((ctx
->conninfo
->version
= strdup(tmp
)) == NULL
)
261 if (tls_get_peer_cert_info(ctx
) == -1)
264 if (tls_conninfo_cert_pem(ctx
) == -1)
267 if (tls_conninfo_session(ctx
) == -1)
273 tls_conninfo_free(ctx
->conninfo
);
274 ctx
->conninfo
= NULL
;
280 tls_conninfo_free(struct tls_conninfo
*conninfo
)
282 if (conninfo
== NULL
)
285 free(conninfo
->alpn
);
286 free(conninfo
->cipher
);
287 free(conninfo
->servername
);
288 free(conninfo
->version
);
290 free(conninfo
->hash
);
291 free(conninfo
->issuer
);
292 free(conninfo
->subject
);
294 free(conninfo
->peer_cert
);
300 tls_conn_alpn_selected(struct tls
*ctx
)
302 if (ctx
->conninfo
== NULL
)
304 return (ctx
->conninfo
->alpn
);
308 tls_conn_cipher(struct tls
*ctx
)
310 if (ctx
->conninfo
== NULL
)
312 return (ctx
->conninfo
->cipher
);
316 tls_conn_servername(struct tls
*ctx
)
318 if (ctx
->conninfo
== NULL
)
320 return (ctx
->conninfo
->servername
);
324 tls_conn_session_resumed(struct tls
*ctx
)
326 if (ctx
->conninfo
== NULL
)
328 return (ctx
->conninfo
->session_resumed
);
332 tls_conn_version(struct tls
*ctx
)
334 if (ctx
->conninfo
== NULL
)
336 return (ctx
->conninfo
->version
);