summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbeck <>2016-11-02 15:18:42 +0000
committerbeck <>2016-11-02 15:18:42 +0000
commit8cc868305fe197edb9f01ce424e355d76be91b22 (patch)
treed759e28afc9aedffba6861487c1680a3f8e3331d /src
parent90c573eba184fe31184d14ce10367f810fa1d417 (diff)
downloadopenbsd-8cc868305fe197edb9f01ce424e355d76be91b22.tar.gz
openbsd-8cc868305fe197edb9f01ce424e355d76be91b22.tar.bz2
openbsd-8cc868305fe197edb9f01ce424e355d76be91b22.zip
Add OCSP client side support to libtls.
- Provide access to certificate OCSP URL - Provide ability to check a raw OCSP reply against an established TLS ctx - Check and validate OCSP stapling info in the TLS handshake if a stapled OCSP response is provided.` Add example code to show OCSP URL and stapled info into netcat. ok jsing@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libtls/Makefile3
-rw-r--r--src/lib/libtls/tls.c7
-rw-r--r--src/lib/libtls/tls.h37
-rw-r--r--src/lib/libtls/tls_client.c12
-rw-r--r--src/lib/libtls/tls_init.3121
-rw-r--r--src/lib/libtls/tls_internal.h33
-rw-r--r--src/lib/libtls/tls_ocsp.c399
-rw-r--r--src/usr.bin/nc/netcat.c38
8 files changed, 641 insertions, 9 deletions
diff --git a/src/lib/libtls/Makefile b/src/lib/libtls/Makefile
index 245b1def6e..f90c57d53f 100644
--- a/src/lib/libtls/Makefile
+++ b/src/lib/libtls/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.25 2016/09/19 03:25:22 bcook Exp $ 1# $OpenBSD: Makefile,v 1.26 2016/11/02 15:18:42 beck Exp $
2 2
3CFLAGS+= -Wall -Werror -Wimplicit 3CFLAGS+= -Wall -Werror -Wimplicit
4CFLAGS+= -DLIBRESSL_INTERNAL 4CFLAGS+= -DLIBRESSL_INTERNAL
@@ -20,6 +20,7 @@ SRCS= tls.c \
20 tls_peer.c \ 20 tls_peer.c \
21 tls_server.c \ 21 tls_server.c \
22 tls_util.c \ 22 tls_util.c \
23 tls_ocsp.c \
23 tls_verify.c 24 tls_verify.c
24 25
25MAN= tls_init.3 26MAN= tls_init.3
diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c
index 00564edb3c..cccdb00531 100644
--- a/src/lib/libtls/tls.c
+++ b/src/lib/libtls/tls.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls.c,v 1.49 2016/09/04 12:26:43 bcook Exp $ */ 1/* $OpenBSD: tls.c,v 1.50 2016/11/02 15:18:42 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -419,6 +419,9 @@ tls_reset(struct tls *ctx)
419 tls_conninfo_free(ctx->conninfo); 419 tls_conninfo_free(ctx->conninfo);
420 ctx->conninfo = NULL; 420 ctx->conninfo = NULL;
421 421
422 tls_ocsp_ctx_free(ctx->ocsp_ctx);
423 ctx->ocsp_ctx = NULL;
424
422 for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) { 425 for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) {
423 nsni = sni->next; 426 nsni = sni->next;
424 tls_sni_ctx_free(sni); 427 tls_sni_ctx_free(sni);
@@ -499,6 +502,8 @@ tls_handshake(struct tls *ctx)
499 ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); 502 ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn);
500 if (tls_conninfo_populate(ctx) == -1) 503 if (tls_conninfo_populate(ctx) == -1)
501 rv = -1; 504 rv = -1;
505 if (ctx->ocsp_ctx == NULL)
506 ctx->ocsp_ctx = tls_ocsp_setup_from_peer(ctx);
502 } 507 }
503 out: 508 out:
504 /* Prevent callers from performing incorrect error handling */ 509 /* Prevent callers from performing incorrect error handling */
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h
index 6cc3d0d6f8..3929cb848e 100644
--- a/src/lib/libtls/tls.h
+++ b/src/lib/libtls/tls.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls.h,v 1.38 2016/09/13 13:40:58 tedu Exp $ */ 1/* $OpenBSD: tls.h,v 1.39 2016/11/02 15:18:42 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -41,6 +41,31 @@ extern "C" {
41#define TLS_WANT_POLLIN -2 41#define TLS_WANT_POLLIN -2
42#define TLS_WANT_POLLOUT -3 42#define TLS_WANT_POLLOUT -3
43 43
44/* RFC 6960 Section 2.3 */
45#define TLS_OCSP_RESPONSE_SUCCESSFUL 0
46#define TLS_OCSP_RESPONSE_MALFORMED 1
47#define TLS_OCSP_RESPONSE_INTERNALERROR 2
48#define TLS_OCSP_RESPONSE_TRYLATER 3
49#define TLS_OCSP_RESPONSE_SIGREQUIRED 4
50#define TLS_OCSP_RESPONSE_UNAUTHORIZED 5
51
52/* RFC 6960 Section 2.2 */
53#define TLS_OCSP_CERT_GOOD 0
54#define TLS_OCSP_CERT_REVOKED 1
55#define TLS_OCSP_CERT_UNKNOWN 2
56
57/* RFC 5280 Section 5.3.1 */
58#define TLS_CRL_REASON_UNSPECIFIED 0
59#define TLS_CRL_REASON_KEY_COMPROMISE 1
60#define TLS_CRL_REASON_CA_COMPROMISE 2
61#define TLS_CRL_REASON_AFFILIATION_CHANGED 3
62#define TLS_CRL_REASON_SUPERSEDED 4
63#define TLS_CRL_REASON_CESSATION_OF_OPERATION 5
64#define TLS_CRL_REASON_CERTIFICATE_HOLD 6
65#define TLS_CRL_REASON_REMOVE_FROM_CRL 8
66#define TLS_CRL_REASON_PRIVILEGE_WITHDRAWN 9
67#define TLS_CRL_REASON_AA_COMPROMISE 10
68
44struct tls; 69struct tls;
45struct tls_config; 70struct tls_config;
46 71
@@ -138,6 +163,16 @@ const char *tls_conn_version(struct tls *_ctx);
138 163
139uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); 164uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password);
140 165
166int tls_ocsp_process_response(struct tls *_ctx, const unsigned char *_response, size_t _size);
167int tls_peer_ocsp_cert_status(struct tls *_ctx);
168int tls_peer_ocsp_crl_reason(struct tls *_ctx);
169time_t tls_peer_ocsp_next_update(struct tls *_ctx);
170int tls_peer_ocsp_response_status(struct tls *_ctx);
171const char *tls_peer_ocsp_result(struct tls *_ctx);
172time_t tls_peer_ocsp_revocation_time(struct tls *_ctx);
173time_t tls_peer_ocsp_this_update(struct tls *_ctx);
174const char *tls_peer_ocsp_url(struct tls *_ctx);
175
141#ifdef __cplusplus 176#ifdef __cplusplus
142} 177}
143#endif 178#endif
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c
index a1bceb7d97..84f4e91740 100644
--- a/src/lib/libtls/tls_client.c
+++ b/src/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_client.c,v 1.36 2016/09/04 13:20:56 jsing Exp $ */ 1/* $OpenBSD: tls_client.c,v 1.37 2016/11/02 15:18:42 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -200,6 +200,11 @@ tls_connect_common(struct tls *ctx, const char *servername)
200 SSL_VERIFY_PEER) == -1)) 200 SSL_VERIFY_PEER) == -1))
201 goto err; 201 goto err;
202 202
203 if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) {
204 tls_set_errorx(ctx, "ssl OCSP verification setup failure");
205 goto err;
206 }
207
203 if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { 208 if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
204 tls_set_errorx(ctx, "ssl connection failure"); 209 tls_set_errorx(ctx, "ssl connection failure");
205 goto err; 210 goto err;
@@ -210,6 +215,11 @@ tls_connect_common(struct tls *ctx, const char *servername)
210 goto err; 215 goto err;
211 } 216 }
212 217
218 if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) {
219 tls_set_errorx(ctx, "ssl OCSP extension setup failure");
220 goto err;
221 }
222
213 /* 223 /*
214 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not 224 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
215 * permitted in "HostName". 225 * permitted in "HostName".
diff --git a/src/lib/libtls/tls_init.3 b/src/lib/libtls/tls_init.3
index 6059c3f8a0..2f6ca3d802 100644
--- a/src/lib/libtls/tls_init.3
+++ b/src/lib/libtls/tls_init.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: tls_init.3,v 1.72 2016/09/13 13:40:58 tedu Exp $ 1.\" $OpenBSD: tls_init.3,v 1.73 2016/11/02 15:18:42 beck Exp $
2.\" 2.\"
3.\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> 3.\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
4.\" 4.\"
@@ -14,7 +14,7 @@
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\" 16.\"
17.Dd $Mdocdate: September 13 2016 $ 17.Dd $Mdocdate: November 2 2016 $
18.Dt TLS_INIT 3 18.Dt TLS_INIT 3
19.Os 19.Os
20.Sh NAME 20.Sh NAME
@@ -50,6 +50,7 @@
50.Nm tls_config_verify , 50.Nm tls_config_verify ,
51.Nm tls_config_verify_client , 51.Nm tls_config_verify_client ,
52.Nm tls_config_verify_client_optional , 52.Nm tls_config_verify_client_optional ,
53.Nm tls_ocsp_process_response,
53.Nm tls_peer_cert_provided , 54.Nm tls_peer_cert_provided ,
54.Nm tls_peer_cert_contains_name , 55.Nm tls_peer_cert_contains_name ,
55.Nm tls_peer_cert_issuer , 56.Nm tls_peer_cert_issuer ,
@@ -57,6 +58,14 @@
57.Nm tls_peer_cert_hash , 58.Nm tls_peer_cert_hash ,
58.Nm tls_peer_cert_notbefore , 59.Nm tls_peer_cert_notbefore ,
59.Nm tls_peer_cert_notafter , 60.Nm tls_peer_cert_notafter ,
61.Nm tls_peer_ocsp_cert_status,
62.Nm tls_peer_ocsp_crl_reason,
63.Nm tls_peer_ocsp_next_update,
64.Nm tls_peer_ocsp_response_status,
65.Nm tls_peer_ocsp_result_msg,
66.Nm tls_peer_ocsp_revocation_time,
67.Nm tls_peer_ocsp_this_update,
68.Nm tls_peer_ocsp_url,
60.Nm tls_conn_alpn_selected , 69.Nm tls_conn_alpn_selected ,
61.Nm tls_conn_cipher , 70.Nm tls_conn_cipher ,
62.Nm tls_conn_servername , 71.Nm tls_conn_servername ,
@@ -160,6 +169,24 @@
160.Fn tls_peer_cert_notbefore "struct tls *ctx" 169.Fn tls_peer_cert_notbefore "struct tls *ctx"
161.Ft "time_t" 170.Ft "time_t"
162.Fn tls_peer_cert_notafter "struct tls *ctx" 171.Fn tls_peer_cert_notafter "struct tls *ctx"
172.Ft "int"
173.Fn tls_ocsp_process_response "struct tls *ctx" "const unsigned char *response" "size_t size"
174.Ft "int"
175.Fn tls_peer_ocsp_cert_status "struct tls *ctx"
176.Ft "int"
177.Fn tls_peer_ocsp_crl_reason "struct tls *ctx"
178.Ft time_t
179.Fn tls_peer_ocsp_next_update "struct tls *ctx"
180.Ft "int"
181.Fn tls_peer_ocsp_response_status "struct tls *ctx"
182.Ft "const char *"
183.Fn tls_peer_ocsp_result_msg "struct tls *ctx"
184.Ft "time_t"
185.Fn tls_peer_ocsp_revocation_time "struct tls *ctx"
186.Ft "time_t"
187.Fn tls_peer_ocsp_this_update" struct tls *ctx"
188.Ft "const char *"
189.Fn tls_peer_ocsp_url "struct tls *ctx"
163.Ft "const char *" 190.Ft "const char *"
164.Fn tls_conn_alpn_selected "struct tls *ctx" 191.Fn tls_conn_alpn_selected "struct tls *ctx"
165.Ft "const char *" 192.Ft "const char *"
@@ -513,6 +540,53 @@ the peer certificate from
513returns the time corresponding to the end of the validity period of 540returns the time corresponding to the end of the validity period of
514the peer certificate from 541the peer certificate from
515.Ar ctx . 542.Ar ctx .
543.Ed
544.It
545.Fn tls_ocsp_process_response
546processes a raw ocsp response in
547.Ar response
548of size
549.Ar size
550to check the revocation status of the peer certificate from
551.Ar ctx .
552A successful return code of 0 indicates that the certificate has not been revoked.
553.Ed
554.It
555.Fn tls_peer_ocsp_url
556returns the URL for OCSP validation of the peer certificate from
557.Ar ctx
558.El
559.Pp
560The following functions return informaiton about the peer certificate from
561.Ar ctx
562tha was obtained by validating a stapled OCSP response during the handshake, or
563via a previous call to
564.Xr tls_ocsp_process_response
565.Bl -bullet -offset four
566.It
567.Fn tls_peer_ocsp_cert_status
568returns the OCSP certificate status code as per RFC 6960 section 2.2
569.Ed
570.It
571.Fn tls_peer_ocsp_crl_reason
572returns the OCSP certificate revocation reason status code as per RFC 5280
573section 5.3.1
574.Ed
575.It
576.Fn tls_peer_ocsp_next_update
577returns the OCSP next update time
578.Ed
579.It
580.Fn tls_peer_ocsp_response_status
581returns the OCSP response status as per RFC 6960 section 2.3
582.Ed
583.It
584.Fn tls_peer_ocsp_revocation_time
585returns the OCSP revocation time
586.Ed
587.It
588.Fn tls_peer_ocsp_this_update
589returns the OCSP this update time
516.El 590.El
517.Pp 591.Pp
518The following are TLS related utility functions: 592The following are TLS related utility functions:
@@ -616,16 +690,57 @@ The
616and 690and
617.Fn tls_peer_cert_contains_name 691.Fn tls_peer_cert_contains_name
618functions return 1 if the check succeeds, and 0 if it does not. 692functions return 1 if the check succeeds, and 0 if it does not.
693.Pp
619Functions that return a 694Functions that return a
620.Vt time_t 695.Vt time_t
621will return a time in epoch-seconds on success, and -1 on error. 696will return a time in epoch-seconds on success, and -1 on error.
697.Pp
622Functions that return a 698Functions that return a
623.Vt ssize_t 699.Vt ssize_t
624will return a size on success, and -1 on error. 700will return a size on success, and -1 on error.
701.Pp
702The
703.Fn tls_peer_ocsp_response_status
704function returns one of
705.Ar TLS_OCSP_RESPONSE_SUCCESSFUL ,
706.Ar TLS_OCSP_RESPONSE_MALFORMED ,
707.Ar TLS_OCSP_RESPONSE_INTERNALERROR ,
708.Ar TLS_OCSP_RESPONSE_TRYLATER ,
709.Ar TLS_OCSP_RESPONSE_SIGREQUIRED ,
710or
711.AR TLS_OCSP_RESPONSE_UNAUTHORIZED
712on success, and -1 on error.
713.Pp
714The
715.Fn tls_peer_ocsp_cert_status
716function returns one of
717.Ar TLS_OCSP_CERT_GOOD ,
718.Ar TLS_OCSP_CERT_REVOKED ,
719or
720.Ar TLS_OCSP_CERT_UNKNOWN
721on success, and -1 on error.
722.Pp
723The
724.Fn tls_peer_ocsp_crl_reason
725function returns one of
726.Ar TLS_CRL_REASON_UNSPECIFIED ,
727.Ar TLS_CRL_REASON_KEY_COMPROMISE ,
728.Ar TLS_CRL_REASON_CA_COMPROMISE ,
729.Ar TLS_CRL_REASON_AFFILIATION_CHANGED ,
730.Ar TLS_CRL_REASON_SUPERSEDED ,
731.Ar TLS_CRL_REASON_CESSATION_OF_OPERATION ,
732.Ar TLS_CRL_REASON_CERTIFICATE_HOLD ,
733.Ar TLS_CRL_REASON_REMOVE_FROM_CRL ,
734.Ar TLS_CRL_REASON_PRIVILEGE_WITHDRAWN ,
735or
736.Ar TLS_CRL_REASON_AA_COMPROMISE
737on success, and -1 on error.
738.Pp
625All other functions that return 739All other functions that return
626.Vt int 740.Vt int
627will return 0 on success and -1 on error. 741will return 0 on success and -1 on error.
628Functions that return a pointer will return NULL on error, which indicates an 742.Pp
743Functions that return a pointer will return NULL on error or an
629out of memory condition. 744out of memory condition.
630.Pp 745.Pp
631The 746The
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h
index c272038055..df35db37f2 100644
--- a/src/lib/libtls/tls_internal.h
+++ b/src/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_internal.h,v 1.43 2016/09/04 12:26:43 bcook Exp $ */ 1/* $OpenBSD: tls_internal.h,v 1.44 2016/11/02 15:18:42 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> 3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -92,6 +92,31 @@ struct tls_conninfo {
92#define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0) 92#define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0)
93#define TLS_HANDSHAKE_COMPLETE (1 << 1) 93#define TLS_HANDSHAKE_COMPLETE (1 << 1)
94 94
95struct tls_ocsp_result {
96 const char *result_msg;
97 int response_status;
98 int cert_status;
99 int crl_reason;
100 time_t this_update;
101 time_t next_update;
102 time_t revocation_time;
103};
104
105struct tls_ocsp_ctx {
106 /* responder location */
107 char *ocsp_url;
108
109 /* request blob */
110 uint8_t *request_data;
111 size_t request_size;
112
113 /* cert data, this struct does not own these */
114 X509 *main_cert;
115 STACK_OF(X509) *extra_certs;
116
117 struct tls_ocsp_result *ocsp_result;
118};
119
95struct tls_sni_ctx { 120struct tls_sni_ctx {
96 struct tls_sni_ctx *next; 121 struct tls_sni_ctx *next;
97 122
@@ -118,6 +143,8 @@ struct tls {
118 143
119 struct tls_conninfo *conninfo; 144 struct tls_conninfo *conninfo;
120 145
146 struct tls_ocsp_ctx *ocsp_ctx;
147
121 tls_read_cb read_cb; 148 tls_read_cb read_cb;
122 tls_write_cb write_cb; 149 tls_write_cb write_cb;
123 void *cb_arg; 150 void *cb_arg;
@@ -172,6 +199,10 @@ int tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret,
172int tls_conninfo_populate(struct tls *ctx); 199int tls_conninfo_populate(struct tls *ctx);
173void tls_conninfo_free(struct tls_conninfo *conninfo); 200void tls_conninfo_free(struct tls_conninfo *conninfo);
174 201
202int tls_ocsp_verify_cb(SSL *ssl, void *arg);
203void tls_ocsp_ctx_free(struct tls_ocsp_ctx *ctx);
204struct tls_ocsp_ctx *tls_ocsp_setup_from_peer(struct tls *ctx);
205
175int asn1_time_parse(const char *, size_t, struct tm *, int); 206int asn1_time_parse(const char *, size_t, struct tm *, int);
176 207
177#endif /* HEADER_TLS_INTERNAL_H */ 208#endif /* HEADER_TLS_INTERNAL_H */
diff --git a/src/lib/libtls/tls_ocsp.c b/src/lib/libtls/tls_ocsp.c
new file mode 100644
index 0000000000..113ab0dd3d
--- /dev/null
+++ b/src/lib/libtls/tls_ocsp.c
@@ -0,0 +1,399 @@
1/*
2 * Copyright (c) 2015 Marko Kreen <markokr@gmail.com>
3 * Copyright (c) 2016 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19
20#include <arpa/inet.h>
21#include <netinet/in.h>
22
23#include <openssl/err.h>
24#include <openssl/ocsp.h>
25#include <openssl/x509.h>
26
27#include <tls.h>
28#include "tls_internal.h"
29
30#define MAXAGE_SEC (14*24*60*60)
31#define JITTER_SEC (60)
32
33/*
34 * State for request.
35 */
36
37static struct tls_ocsp_ctx *
38tls_ocsp_ctx_new(void)
39{
40 return (calloc(1, sizeof(struct tls_ocsp_ctx)));
41}
42
43void
44tls_ocsp_ctx_free(struct tls_ocsp_ctx *ocsp_ctx)
45{
46 if (ocsp_ctx == NULL)
47 return;
48
49 free(ocsp_ctx->ocsp_result);
50 ocsp_ctx->ocsp_result = NULL;
51 free(ocsp_ctx->ocsp_url);
52 ocsp_ctx->ocsp_url = NULL;
53 free(ocsp_ctx->request_data);
54 ocsp_ctx->request_data = NULL;
55 free(ocsp_ctx);
56}
57
58static int
59tls_ocsp_asn1_parse_time(struct tls *ctx, ASN1_GENERALIZEDTIME *gt, time_t *time)
60{
61 struct tm tm;
62
63 if (gt == NULL)
64 return -1;
65 /* RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME */
66 if (asn1_time_parse(gt->data, gt->length, &tm,
67 V_ASN1_GENERALIZEDTIME) == -1)
68 return -1;
69 if ((*time = timegm(&tm)) == -1)
70 return -1;
71 return 0;
72}
73
74static int
75tls_ocsp_fill_info(struct tls *ctx, int response_status, int cert_status,
76 int crl_reason, ASN1_GENERALIZEDTIME *revtime,
77 ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd)
78{
79 struct tls_ocsp_result *info = NULL;
80
81 free(ctx->ocsp_ctx->ocsp_result);
82 ctx->ocsp_ctx->ocsp_result = NULL;
83
84 if ((info = calloc(1, sizeof (struct tls_ocsp_result))) == NULL) {
85 tls_set_error(ctx, "calloc");
86 return -1;
87 }
88 info->response_status = response_status;
89 info->cert_status = cert_status;
90 info->crl_reason = crl_reason;
91 if (info->response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
92 info->result_msg =
93 OCSP_response_status_str(info->response_status);
94 } else if (info->cert_status != V_OCSP_CERTSTATUS_REVOKED) {
95 info->result_msg = OCSP_cert_status_str(info->cert_status);
96 } else {
97 info->result_msg = OCSP_crl_reason_str(info->crl_reason);
98 }
99 info->revocation_time = info->this_update = info->next_update = -1;
100 if (revtime != NULL &&
101 tls_ocsp_asn1_parse_time(ctx, revtime, &info->revocation_time) != 0) {
102 tls_set_error(ctx,
103 "unable to parse revocation time in OCSP reply");
104 goto error;
105 }
106 if (thisupd != NULL &&
107 tls_ocsp_asn1_parse_time(ctx, thisupd, &info->this_update) != 0) {
108 tls_set_error(ctx,
109 "unable to parse this update time in OCSP reply");
110 goto error;
111 }
112 if (nextupd != NULL &&
113 tls_ocsp_asn1_parse_time(ctx, nextupd, &info->next_update) != 0) {
114 tls_set_error(ctx,
115 "unable to parse next update time in OCSP reply");
116 goto error;
117 }
118 ctx->ocsp_ctx->ocsp_result = info;
119 return 0;
120 error:
121 free(info);
122 return -1;
123}
124
125static OCSP_CERTID *
126tls_ocsp_get_certid(X509 *main_cert, STACK_OF(X509) *extra_certs,
127 SSL_CTX *ssl_ctx)
128{
129 X509_NAME *issuer_name;
130 X509 *issuer;
131 X509_STORE_CTX storectx;
132 X509_OBJECT tmpobj;
133 OCSP_CERTID *cid = NULL;
134 X509_STORE *store;
135
136 if ((issuer_name = X509_get_issuer_name(main_cert)) == NULL)
137 return NULL;
138
139 if (extra_certs != NULL) {
140 issuer = X509_find_by_subject(extra_certs, issuer_name);
141 if (issuer != NULL)
142 return OCSP_cert_to_id(NULL, main_cert, issuer);
143 }
144
145 if ((store = SSL_CTX_get_cert_store(ssl_ctx)) == NULL)
146 return NULL;
147 if (X509_STORE_CTX_init(&storectx, store, main_cert, extra_certs) != 1)
148 return NULL;
149 if (X509_STORE_get_by_subject(&storectx, X509_LU_X509, issuer_name,
150 &tmpobj) == 1) {
151 cid = OCSP_cert_to_id(NULL, main_cert, tmpobj.data.x509);
152 X509_OBJECT_free_contents(&tmpobj);
153 }
154 X509_STORE_CTX_cleanup(&storectx);
155 return cid;
156}
157
158struct tls_ocsp_ctx *
159tls_ocsp_setup_from_peer(struct tls *ctx)
160{
161 struct tls_ocsp_ctx *ocsp_ctx = NULL;
162 STACK_OF(OPENSSL_STRING) *ocsp_urls = NULL;
163
164 if ((ocsp_ctx = tls_ocsp_ctx_new()) == NULL)
165 goto failed;
166
167 /* steal state from ctx struct */
168 ocsp_ctx->main_cert = SSL_get_peer_certificate(ctx->ssl_conn);
169 ocsp_ctx->extra_certs = SSL_get_peer_cert_chain(ctx->ssl_conn);
170 if (ocsp_ctx->main_cert == NULL) {
171 tls_set_errorx(ctx, "no peer certificate for OCSP");
172 goto failed;
173 }
174
175 ocsp_urls = X509_get1_ocsp(ocsp_ctx->main_cert);
176 if (ocsp_urls == NULL)
177 goto failed;
178 ocsp_ctx->ocsp_url = strdup(sk_OPENSSL_STRING_value(ocsp_urls, 0));
179 if (ocsp_ctx->ocsp_url == NULL) {
180 tls_set_errorx(ctx, "out of memory");
181 goto failed;
182 }
183
184 X509_email_free(ocsp_urls);
185 return ocsp_ctx;
186
187 failed:
188 tls_ocsp_ctx_free(ocsp_ctx);
189 X509_email_free(ocsp_urls);
190 return NULL;
191}
192
193static int
194tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp)
195{
196 OCSP_BASICRESP *br = NULL;
197 ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL;
198 OCSP_CERTID *cid = NULL;
199 STACK_OF(X509) *combined = NULL;
200 int response_status=0, cert_status=0, crl_reason=0;
201 int ret = -1;
202 unsigned long flags;
203
204 if ((br = OCSP_response_get1_basic(resp)) == NULL) {
205 tls_set_errorx(ctx, "cannot load ocsp reply");
206 goto error;
207 }
208
209 /*
210 * Skip validation of 'extra_certs' as this should be done
211 * already as part of main handshake.
212 */
213 flags = OCSP_TRUSTOTHER;
214
215 /* now verify */
216 if (OCSP_basic_verify(br, ctx->ocsp_ctx->extra_certs,
217 SSL_CTX_get_cert_store(ctx->ssl_ctx), flags) != 1) {
218 tls_set_error(ctx, "ocsp verify failed");
219 goto error;
220 }
221
222 /* signature OK, look inside */
223 response_status = OCSP_response_status(resp);
224 if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
225 tls_set_errorx(ctx, "ocsp verify failed: response - %s",
226 OCSP_response_status_str(response_status));
227 goto error;
228 }
229
230 cid = tls_ocsp_get_certid(ctx->ocsp_ctx->main_cert,
231 ctx->ocsp_ctx->extra_certs, ctx->ssl_ctx);
232 if (cid == NULL) {
233 tls_set_errorx(ctx, "ocsp verify failed: no issuer cert");
234 goto error;
235 }
236
237 if (OCSP_resp_find_status(br, cid, &cert_status, &crl_reason,
238 &revtime, &thisupd, &nextupd) != 1) {
239 tls_set_errorx(ctx, "ocsp verify failed: no result for cert");
240 goto error;
241 }
242
243 if (OCSP_check_validity(thisupd, nextupd, JITTER_SEC,
244 MAXAGE_SEC) != 1) {
245 tls_set_errorx(ctx,
246 "ocsp verify failed: ocsp response not current");
247 goto error;
248 }
249
250 if (tls_ocsp_fill_info(ctx, response_status, cert_status,
251 crl_reason, revtime, thisupd, nextupd) != 0)
252 goto error;
253
254 /* finally can look at status */
255 if (cert_status != V_OCSP_CERTSTATUS_GOOD && cert_status !=
256 V_OCSP_CERTSTATUS_UNKNOWN) {
257 tls_set_errorx(ctx, "ocsp verify failed: revoked cert - %s",
258 OCSP_crl_reason_str(crl_reason));
259 goto error;
260 }
261
262 ret = 0;
263
264 error:
265 sk_X509_free(combined);
266 OCSP_CERTID_free(cid);
267 OCSP_BASICRESP_free(br);
268 return ret;
269}
270
271/* TLS handshake verification callback for stapled requests */
272int
273tls_ocsp_verify_cb(SSL *ssl, void *arg)
274{
275 const unsigned char *raw = NULL;
276 int size, res = -1;
277 struct tls *ctx;
278
279 if ((ctx = SSL_get_app_data(ssl)) == NULL)
280 return -1;
281
282 size = SSL_get_tlsext_status_ocsp_resp(ssl, &raw);
283 if (size <= 0)
284 return 1;
285
286 tls_ocsp_ctx_free(ctx->ocsp_ctx);
287 ctx->ocsp_ctx = tls_ocsp_setup_from_peer(ctx);
288 if (ctx->ocsp_ctx != NULL)
289 res = tls_ocsp_process_response(ctx, raw, size);
290
291 return (res == 0) ? 1 : 0;
292}
293
294/*
295 * Public API
296 */
297
298/* Retrieve OSCP URL from peer certificate, if present */
299const char *
300tls_peer_ocsp_url(struct tls *ctx)
301{
302 if (ctx->ocsp_ctx == NULL)
303 return NULL;
304 return ctx->ocsp_ctx->ocsp_url;
305}
306
307const char *
308tls_peer_ocsp_result(struct tls *ctx)
309{
310 if (ctx->ocsp_ctx == NULL)
311 return NULL;
312 if (ctx->ocsp_ctx->ocsp_result == NULL)
313 return NULL;
314 return ctx->ocsp_ctx->ocsp_result->result_msg;
315}
316
317int
318tls_peer_ocsp_response_status(struct tls *ctx)
319{
320 if (ctx->ocsp_ctx == NULL)
321 return -1;
322 if (ctx->ocsp_ctx->ocsp_result == NULL)
323 return -1;
324 return ctx->ocsp_ctx->ocsp_result->response_status;
325}
326
327int
328tls_peer_ocsp_cert_status(struct tls *ctx)
329{
330 if (ctx->ocsp_ctx == NULL)
331 return -1;
332 if (ctx->ocsp_ctx->ocsp_result == NULL)
333 return -1;
334 return ctx->ocsp_ctx->ocsp_result->cert_status;
335}
336
337int
338tls_peer_ocsp_crl_reason(struct tls *ctx)
339{
340 if (ctx->ocsp_ctx == NULL)
341 return -1;
342 if (ctx->ocsp_ctx->ocsp_result == NULL)
343 return -1;
344 return ctx->ocsp_ctx->ocsp_result->crl_reason;
345}
346
347time_t
348tls_peer_ocsp_this_update(struct tls *ctx)
349{
350 if (ctx->ocsp_ctx == NULL)
351 return -1;
352 if (ctx->ocsp_ctx->ocsp_result == NULL)
353 return -1;
354 return ctx->ocsp_ctx->ocsp_result->this_update;
355}
356
357time_t
358tls_peer_ocsp_next_update(struct tls *ctx)
359{
360 if (ctx->ocsp_ctx == NULL)
361 return -1;
362 if (ctx->ocsp_ctx->ocsp_result == NULL)
363 return -1;
364 return ctx->ocsp_ctx->ocsp_result->next_update;
365}
366
367time_t
368tls_peer_ocsp_revocation_time(struct tls *ctx)
369{
370 if (ctx->ocsp_ctx == NULL)
371 return -1;
372 if (ctx->ocsp_ctx->ocsp_result == NULL)
373 return -1;
374 return ctx->ocsp_ctx->ocsp_result->revocation_time;
375}
376
377/*
378 * Process a raw OCSP response from an OCSP server request.
379 * OCSP details can then be retrieved with tls_peer_ocsp_* functions.
380 * returns 0 if certificate ok, -1 otherwise.
381 */
382int
383tls_ocsp_process_response(struct tls *ctx, const unsigned char *response,
384 size_t size)
385{
386 int ret;
387 OCSP_RESPONSE *resp;
388
389 resp = d2i_OCSP_RESPONSE(NULL, &response, size);
390 if (resp == NULL) {
391 tls_ocsp_ctx_free(ctx->ocsp_ctx);
392 ctx->ocsp_ctx = NULL;
393 tls_set_error(ctx, "unable to parse OCSP response");
394 return -1;
395 }
396 ret = tls_ocsp_verify_response(ctx, resp);
397 OCSP_RESPONSE_free(resp);
398 return ret;
399}
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index 3af7d50374..64e77a8b52 100644
--- a/src/usr.bin/nc/netcat.c
+++ b/src/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: netcat.c,v 1.163 2016/09/03 17:35:34 bcook Exp $ */ 1/* $OpenBSD: netcat.c,v 1.164 2016/11/02 15:18:42 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * Copyright (c) 2015 Bob Beck. All rights reserved. 4 * Copyright (c) 2015 Bob Beck. All rights reserved.
@@ -1518,6 +1518,8 @@ void
1518report_tls(struct tls * tls_ctx, char * host, char *tls_expectname) 1518report_tls(struct tls * tls_ctx, char * host, char *tls_expectname)
1519{ 1519{
1520 time_t t; 1520 time_t t;
1521 const char *ocsp_url;
1522
1521 fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", 1523 fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n",
1522 tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); 1524 tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host);
1523 fprintf(stderr, "Peer name: %s\n", 1525 fprintf(stderr, "Peer name: %s\n",
@@ -1535,6 +1537,40 @@ report_tls(struct tls * tls_ctx, char * host, char *tls_expectname)
1535 if (tls_peer_cert_hash(tls_ctx)) 1537 if (tls_peer_cert_hash(tls_ctx))
1536 fprintf(stderr, "Cert Hash: %s\n", 1538 fprintf(stderr, "Cert Hash: %s\n",
1537 tls_peer_cert_hash(tls_ctx)); 1539 tls_peer_cert_hash(tls_ctx));
1540 ocsp_url = tls_peer_ocsp_url(tls_ctx);
1541 fprintf(stderr, "OCSP URL: %s\n", ocsp_url == NULL ? "" : ocsp_url);
1542 fprintf(stderr, "OCSP Stapling:");
1543 switch (tls_peer_ocsp_response_status(tls_ctx)) {
1544 case TLS_OCSP_RESPONSE_SUCCESSFUL:
1545 fprintf(stderr, " %s\n",
1546 tls_peer_ocsp_result(tls_ctx) == NULL ? "" :
1547 tls_peer_ocsp_result(tls_ctx));
1548 fprintf(stderr,
1549 " response_status=%d cert_status=%d crl_reason=%d\n",
1550 tls_peer_ocsp_response_status(tls_ctx),
1551 tls_peer_ocsp_cert_status(tls_ctx),
1552 tls_peer_ocsp_crl_reason(tls_ctx));
1553 t = tls_peer_ocsp_this_update(tls_ctx);
1554 fprintf(stderr, " this update: %s",
1555 t != -1 ? ctime(&t) : "\n");
1556 t = tls_peer_ocsp_next_update(tls_ctx);
1557 fprintf(stderr, " next update: %s",
1558 t != -1 ? ctime(&t) : "\n");
1559 t = tls_peer_ocsp_revocation_time(tls_ctx);
1560 fprintf(stderr, " revocation: %s",
1561 t != -1 ? ctime(&t) : "\n");
1562 break;
1563 case -1:
1564 fprintf(stderr, "\n");
1565 break;
1566 default:
1567 fprintf(stderr, " failure - response_status %d (%s)\n",
1568 tls_peer_ocsp_response_status(tls_ctx),
1569 tls_peer_ocsp_result(tls_ctx) == NULL ? "" :
1570 tls_peer_ocsp_result(tls_ctx));
1571 break;
1572
1573 }
1538} 1574}
1539 1575
1540void 1576void