On Tue, Jul 05, 2016 at 09:11:37PM -0600, Bob Beck wrote:
> Ok, so this work was done by Marko Kreen, all as the result of a very long 
> discussion in:
> 
> https://github.com/libressl-portable/openbsd/pull/47
> 
> In a nutshell, I threw down a glove that libtls could have functions to 
> support OCSP, and
> make it where a client could write ocsp stuff, but I would resist making 
> libtls be
> and http library that does that for you.  I challenged him to add the 
> necessary support
> functions so it was possible to write a client. 
> 
> He delivered, and I've cleaned a few things up in it. (after a long delay 
> which
> I apologize for)
> 
> Attached to this message is marko's test program, which uses libcurl - The 
> diff is
> for our libtls, and I've been able to compile and use his test program with 
> it:

Ok, here's a revised diff for this to handle the recent libtls changes. 

Included in this diff (but would be committed separately) are modifications
to nc so that nc will show both the OCSP URL in a connected certificate, and
the OCSP stapling informaiton if it is there in a similar manner to
marko kreen's test program:

# nc -c -v www.openbsd.org 443
Connection to www.openbsd.org 443 port [tcp/https] succeeded!
TLS handshake negotiated TLSv1.2/ECDHE-RSA-CHACHA20-POLY1305 with host 
www.openbsd.org
Peer name: www.openbsd.org
Subject: /CN=www.openbsd.org
Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Valid From: Sat Aug  6 16:41:00 2016
Valid Until: Fri Nov  4 16:41:00 2016
Cert Hash: 
SHA256:76a8ebf241afca46ebb3a88a2f28d0d3b31650b479a27eeae0a67eb53195437c
OCSP URL: http://ocsp.int-x3.letsencrypt.org/
OCSP Stapling: no-ocsp

# nc -c -v cloudflare.com 443                                                
Connection to cloudflare.com 443 port [tcp/https] succeeded!
TLS handshake negotiated TLSv1.2/ECDHE-ECDSA-AES128-GCM-SHA256 with host 
cloudflare.com
Peer name: cloudflare.com
Subject: 
/serialNumber=4710875/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/businessCategory=Private
 Organization/C=US/postalCode=94107/ST=California/L=San Francisco/street=655 
Third Street, Suite 200/O=CloudFlare, Inc./OU=COMODO EV Multi-Domain SSL
Issuer: /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC 
Extended Validation Secure Server CA
Valid From: Mon Nov 30 17:00:00 2015
Valid Until: Wed Nov 30 16:59:59 2016
Cert Hash: 
SHA256:e5554e6a21828b6f17546c2b77227f37003c7a092693beb394beeff80a735880
OCSP URL: http://ocsp.comodoca.com
OCSP Stapling: good
  req_status=0 cert_status=0 crl_reason=0
  this update Sun Aug 21 23:34:02 2016
  next update Thu Aug 25 23:34:02 2016
  revocation N/A

marko's test program is in the attachment (It uses libcurl to retrieve the OCSP
info from the URL - nc does not do this). 

Looking to get this in and polish in tree. I'll add man pages once I get 
feedback
on the API. 


Index: lib/libtls/Makefile
===================================================================
RCS file: /cvs/src/lib/libtls/Makefile,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 Makefile
--- lib/libtls/Makefile 30 Mar 2016 06:38:43 -0000      1.23
+++ lib/libtls/Makefile 23 Aug 2016 02:06:17 -0000
@@ -19,6 +19,7 @@ SRCS= tls.c \
        tls_peer.c \
        tls_server.c \
        tls_util.c \
+       tls_ocsp.c \
        tls_verify.c
 
 MAN=   tls_init.3
Index: lib/libtls/tls.h
===================================================================
RCS file: /cvs/src/lib/libtls/tls.h,v
retrieving revision 1.35
diff -u -p -u -p -r1.35 tls.h
--- lib/libtls/tls.h    22 Aug 2016 14:58:26 -0000      1.35
+++ lib/libtls/tls.h    23 Aug 2016 02:41:30 -0000
@@ -40,6 +40,29 @@ extern "C" {
 
 #define TLS_WANT_POLLIN                -2
 #define TLS_WANT_POLLOUT       -3
+#define TLS_NO_OCSP            -4
+
+#define TLS_OCSP_RESPONSE_SUCCESSFUL           0
+#define TLS_OCSP_RESPONSE_MALFORMED            1
+#define TLS_OCSP_RESPONSE_INTERNALERR          2
+#define TLS_OCSP_RESPONSE_TRYLATER             3
+#define TLS_OCSP_RESPONSE_SIGREQUIRED          5
+#define TLS_OCSP_RESPONSE_UNAUTHORIZED         6
+
+#define TLS_OCSP_CERT_GOOD                     0
+#define TLS_OCSP_CERT_REVOKED                  1
+#define TLS_OCSP_CERT_UNKNOWN                  2
+
+#define TLS_CRL_REASON_UNPSECIFIED             0
+#define TLS_CRL_REASON_KEY_COMPROMISE          1
+#define TLS_CRL_REASON_CA_COMPROMISE           2
+#define TLS_CRL_REASON_AFFILIATION_CHANGED     3
+#define TLS_CRL_REASON_SUPERSEDED              4
+#define TLS_CRL_REASON_CESSATION_OF_OPERATION  5
+#define TLS_CRL_REASON_CERTIFICATE_HOLD                6
+#define TLS_CRL_REASON_REMOVE_FROM_CRL         8
+#define TLS_CRL_REASON_PRIVILEGE_WITH_DRAWN    9
+#define TLS_CRL_REASON_AA_COMPROMISE           10
 
 struct tls;
 struct tls_config;
@@ -76,6 +99,8 @@ int tls_config_set_keypair_file(struct t
     const char *_cert_file, const char *_key_file);
 int tls_config_set_keypair_mem(struct tls_config *_config, const uint8_t 
*_cert,
     size_t _cert_len, const uint8_t *_key, size_t _key_len);
+int tls_config_set_ocsp_stapling_file(struct tls_config *_config, const char 
*_blob_file);
+int tls_config_set_ocsp_stapling_mem(struct tls_config *_config, const uint8_t 
*_blob, size_t _len);
 void tls_config_set_protocols(struct tls_config *_config, uint32_t _protocols);
 void tls_config_set_verify_depth(struct tls_config *_config, int 
_verify_depth);
 
@@ -128,6 +153,18 @@ const char *tls_conn_servername(struct t
 const char *tls_conn_version(struct tls *_ctx);
 
 uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password);
+
+int tls_get_ocsp_info(struct tls *ctx, int *response_status, int *cert_status, 
int *crl_reason,
+                     time_t *this_update, time_t *next_update, time_t 
*revoction_time,
+                     const char **result_text);
+
+int tls_ocsp_check_peer_request(struct tls **ocsp_ctx_p, struct tls *target,
+                           char **ocsp_url, void **request_blob, size_t 
*request_size);
+
+int tls_ocsp_refresh_stapling_request(struct tls **ocsp_ctx_p, struct 
tls_config *config,
+               char **ocsp_url, void **request_blob, size_t *request_size);
+
+int tls_ocsp_process_response(struct tls *ctx, const void *response_blob, 
size_t size);
 
 #ifdef __cplusplus
 }
Index: lib/libtls/tls_client.c
===================================================================
RCS file: /cvs/src/lib/libtls/tls_client.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 tls_client.c
--- lib/libtls/tls_client.c     15 Aug 2016 14:04:23 -0000      1.34
+++ lib/libtls/tls_client.c     23 Aug 2016 02:06:17 -0000
@@ -210,6 +210,11 @@ tls_connect_fds(struct tls *ctx, int fd_
             SSL_VERIFY_PEER) == -1))
                goto err;
 
+       if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, 
tls_ocsp_verify_callback) != 1) {
+               tls_set_errorx(ctx, "ssl OCSP verification setup failure");
+               goto err;
+       }
+
        if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
                tls_set_errorx(ctx, "ssl connection failure");
                goto err;
@@ -221,6 +226,10 @@ tls_connect_fds(struct tls *ctx, int fd_
        if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
            SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
                tls_set_errorx(ctx, "ssl file descriptor failure");
+               goto err;
+       }
+       if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) 
!= 1) {
+               tls_set_errorx(ctx, "ssl OCSP extension setup failure");
                goto err;
        }
 
Index: lib/libtls/tls_config.c
===================================================================
RCS file: /cvs/src/lib/libtls/tls_config.c,v
retrieving revision 1.28
diff -u -p -u -p -r1.28 tls_config.c
--- lib/libtls/tls_config.c     22 Aug 2016 14:55:59 -0000      1.28
+++ lib/libtls/tls_config.c     23 Aug 2016 02:06:17 -0000
@@ -570,6 +570,24 @@ tls_config_set_keypair_mem(struct tls_co
        return (0);
 }
 
+int
+tls_config_set_ocsp_stapling_file(struct tls_config *config, const char 
*blob_file)
+{
+       if (blob_file != NULL)
+               tls_config_set_ocsp_stapling_mem(config, NULL, 0);
+
+       return set_string(&config->ocsp_file, blob_file);
+}
+
+int
+tls_config_set_ocsp_stapling_mem(struct tls_config *config, const uint8_t 
*blob, size_t len)
+{
+       if (blob != NULL)
+               tls_config_set_ocsp_stapling_file(config, NULL);
+
+       return set_mem(&config->ocsp_mem, &config->ocsp_len, blob, len);
+}
+
 void
 tls_config_set_protocols(struct tls_config *config, uint32_t protocols)
 {
Index: lib/libtls/tls_init.3
===================================================================
RCS file: /cvs/src/lib/libtls/tls_init.3,v
retrieving revision 1.67
diff -u -p -u -p -r1.67 tls_init.3
--- lib/libtls/tls_init.3       22 Aug 2016 14:55:59 -0000      1.67
+++ lib/libtls/tls_init.3       23 Aug 2016 02:41:48 -0000
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tls_init.3,v 1.67 2016/08/22 14:55:59 jsing Exp $
+\" $OpenBSD: tls_init.3,v 1.67 2016/08/22 14:55:59 jsing Exp $
 .\"
 .\" Copyright (c) 2014 Ted Unangst <t...@openbsd.org>
 .\"
Index: lib/libtls/tls_internal.h
===================================================================
RCS file: /cvs/src/lib/libtls/tls_internal.h,v
retrieving revision 1.42
diff -u -p -u -p -r1.42 tls_internal.h
--- lib/libtls/tls_internal.h   22 Aug 2016 17:12:35 -0000      1.42
+++ lib/libtls/tls_internal.h   23 Aug 2016 02:09:22 -0000
@@ -63,6 +63,9 @@ struct tls_config {
        int dheparams;
        int ecdhecurve;
        struct tls_keypair *keypair;
+       const char *ocsp_file;
+       char *ocsp_mem;
+       size_t ocsp_len;
        uint32_t protocols;
        int verify_cert;
        int verify_client;
@@ -88,10 +91,14 @@ struct tls_conninfo {
 #define TLS_CLIENT             (1 << 0)
 #define TLS_SERVER             (1 << 1)
 #define TLS_SERVER_CONN                (1 << 2)
+#define TLS_OCSP_CLIENT                (1 << 3)
 
 #define TLS_EOF_NO_CLOSE_NOTIFY        (1 << 0)
 #define TLS_HANDSHAKE_COMPLETE (1 << 1)
 
+struct tls_ocsp_query;
+struct tls_ocsp_info;
+
 struct tls_sni_ctx {
        struct tls_sni_ctx *next;
 
@@ -117,6 +124,20 @@ struct tls {
        X509 *ssl_peer_cert;
 
        struct tls_conninfo *conninfo;
+
+       const char *ocsp_result;
+       struct tls_ocsp_info *ocsp_info;
+
+       struct tls_ocsp_query *ocsp_query;
+};
+
+struct tls_ocsp_info {
+       int response_status;
+       int cert_status;
+       int crl_reason;
+       time_t this_update;
+       time_t next_update;
+       time_t revocation_time;
 };
 
 struct tls_sni_ctx *tls_sni_ctx_new(void);
@@ -164,6 +185,11 @@ int tls_ssl_error(struct tls *ctx, SSL *
 
 int tls_conninfo_populate(struct tls *ctx);
 void tls_conninfo_free(struct tls_conninfo *conninfo);
+
+int tls_ocsp_verify_callback(SSL *ssl, void *arg);
+int tls_ocsp_stapling_callback(SSL *ssl, void *arg);
+void tls_ocsp_client_free(struct tls *ctx);
+void tls_ocsp_info_free(struct tls_ocsp_info *info);
 
 int asn1_time_parse(const char *, size_t, struct tm *, int);
 
Index: lib/libtls/tls_server.c
===================================================================
RCS file: /cvs/src/lib/libtls/tls_server.c,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 tls_server.c
--- lib/libtls/tls_server.c     22 Aug 2016 14:51:37 -0000      1.25
+++ lib/libtls/tls_server.c     23 Aug 2016 02:06:17 -0000
@@ -213,6 +213,11 @@ tls_configure_server_ssl(struct tls *ctx
        if (ctx->config->ciphers_server == 1)
                SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
 
+       if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, 
tls_ocsp_stapling_callback) != 1) {
+               tls_set_errorx(ctx, "ssl OCSP stapling setup failure");
+               goto err;
+       }
+
        /*
         * Set session ID context to a random value.  We don't support
         * persistent caching of sessions so it is OK to set a temporary
Index: usr.bin/nc/netcat.c
===================================================================
RCS file: /cvs/src/usr.bin/nc/netcat.c,v
retrieving revision 1.162
diff -u -p -u -p -r1.162 netcat.c
--- usr.bin/nc/netcat.c 13 Aug 2016 13:09:10 -0000      1.162
+++ usr.bin/nc/netcat.c 23 Aug 2016 03:26:48 -0000
@@ -1517,7 +1517,14 @@ map_tls(char *s, int *val)
 void
 report_tls(struct tls * tls_ctx, char * host, char *tls_expectname)
 {
-       time_t t;
+       int req_status, cert_status, crl_reason, res;
+       const char *msg;
+       time_t t, this_update, next_update, revocation_time;
+       struct tls *ocsp_ctx;
+       char *ocsp_url;
+       void *req_data;
+       size_t req_len;
+
        fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n",
            tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host);
        fprintf(stderr, "Peer name: %s\n",
@@ -1535,6 +1542,23 @@ report_tls(struct tls * tls_ctx, char * 
        if (tls_peer_cert_hash(tls_ctx))
                fprintf(stderr, "Cert Hash: %s\n",
                    tls_peer_cert_hash(tls_ctx));
+       res = tls_ocsp_check_peer_request(&ocsp_ctx, tls_ctx, &ocsp_url,
+                                         &req_data, &req_len);
+       fprintf(stderr, "OCSP URL: %s\n", res == TLS_NO_OCSP ? "N/A" : 
ocsp_url);
+       tls_free(ocsp_ctx);
+       res = tls_get_ocsp_info(tls_ctx, &req_status, &cert_status, &crl_reason,
+           &this_update, &next_update, &revocation_time, &msg);
+       fprintf(stderr, "OCSP Stapling: %s\n", msg);
+       if (res == 0) {
+               fprintf(stderr, "  req_status=%d cert_status=%d 
crl_reason=%d\n",
+                      req_status, cert_status, crl_reason);
+               fprintf(stderr, "  this update %s",
+                   this_update ? ctime(&this_update) : "N/A\n");
+               fprintf(stderr, "  next update %s",
+                   next_update ? ctime(&next_update) : "N/A\n");
+               fprintf(stderr, "  revocation %s",
+                   revocation_time ? ctime(&revocation_time) : "N/A\n");
+       }
 }
 
 void

Attachment: ocsp-connect.tgz
Description: application/tar-gz

Reply via email to