Add libtls functionality for OCSP, and OCSP stapling support - take 2

2016-08-22 Thread Bob Beck
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 -  1.23
+++ lib/libtls/Makefile 23 Aug 2016 02:06:17 -
@@ -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.h22 Aug 2016 14:58:26 -  1.35
+++ lib/libtls/tls.h23 Aug 2016 02:41:30 -
@@ -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_MALFORMED1
+#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_HOLD6
+#define TLS_CRL_REASON_REMOVE_FROM_CRL 8
+#define TLS_CRL_REASON_PRIVILEGE_WITH_DRAWN9
+#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,
   

Re: Add libtls functionality for OCSP, and OCSP stapling support

2016-07-11 Thread Marko Kreen
On Fri, Jul 08, 2016 at 07:20:32PM -0600, Bob Beck wrote:
> One thing I am considering here (and for y'all to know, this is a
> major API addition and won't
> go in until after the soon upcoming openbsd release cycle happens). is
> that the way
> we have done this in the past with libtls is to just - do the thing in
> the handshake and keep
> the data hidden in the (private) conn_info stucture and then
> accessible to the user via a
> tls_ funciton call.
> 
> What strikes me as the most sensible thing to do for staping is to
> just do it in the handshake,
> and then record the status is the conn_info.. So if stapling is
> provided the handshake succeeds
> if the stapled response checks out, fails if it does not with a
> reason, and if it is not present or
> the certifiacat status is indeterminate we then have any designated
> ocsp responders from the
> certificate available to the application to then go make their own
> ocsp calls directly.

That is what the patch is about - after handshake client can call
tls_get_ocsp_info() to see if OCSP stapling was in use.

The responder request stuff is mainly necessary for server to
update it's stapled response.  But it's also possible to
check peer cert via OCSP as it's basically same code.

-- 
marko



Re: Add libtls functionality for OCSP, and OCSP stapling support

2016-07-08 Thread Bob Beck
One thing I am considering here (and for y'all to know, this is a
major API addition and won't
go in until after the soon upcoming openbsd release cycle happens). is
that the way
we have done this in the past with libtls is to just - do the thing in
the handshake and keep
the data hidden in the (private) conn_info stucture and then
accessible to the user via a
tls_ funciton call.

What strikes me as the most sensible thing to do for staping is to
just do it in the handshake,
and then record the status is the conn_info.. So if stapling is
provided the handshake succeeds
if the stapled response checks out, fails if it does not with a
reason, and if it is not present or
the certifiacat status is indeterminate we then have any designated
ocsp responders from the
certificate available to the application to then go make their own
ocsp calls directly.


On Fri, Jul 8, 2016 at 2:40 PM, Marko Kreen  wrote:
> On Wed, Jul 06, 2016 at 08:30:23PM +0900, kinichiro inoguchi wrote:
>> Hi, I have 2 questions about this implementation.
>>
>> 1) Can the OCSP client put multiple certificates to check in the request ?
>>like this.
>> 
>> $ openssl ocsp -reqin ocsp_req.der -req_text
>> OCSP Request Data:
>> Version: 1 (0x0)
>> Requestor List:
>> Certificate ID:
>>   Hash Algorithm: sha1
>>   Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
>>   Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
>>   Serial Number: 03
>> Certificate ID:
>>   Hash Algorithm: sha1
>>   Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
>>   Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
>>   Serial Number: D0F00ED53778C7C5
>> Request Extensions:
>> OCSP Nonce:
>> 04104C65A6FA1D4839916C3B8C18A4EF2E5D
>> 
>
> No.  Current goal is to get stapling working, which deals with
> one cert at a time.
>
> Requesting multiple certs with one request seems dubious even
> in general (rfc6961) case as each cert may potentially have
> different responder.  The API needs to export multiple
> (ocsp_url, request_blob) pairs then.  But there is option
> to embed multiple certs into one request_blob if they
> use same responder, as optimization.
>
>> 2) Is it available signing to OCSP request by client ?
>>I indicate this https://tools.ietf.org/html/rfc6960#section-4.1.2
>>"The requestor MAY choose to sign the OCSP request."
>>
>> These 2 functionality might NOT need when we're doing OCSP stapling.
>> (server cert to verify by OCSP stapling will be always single ...)
>
> No.  It's possible to expose it as option, but why?
>
> Btw, I tried to use OCSP_request_add1_nonce() to add unique nonce to
> reqests, for replay protection.  Common OCSP responders reject such
> requests.  I guess both on performace and security grounds,
> to have dumb responders that do not have access to signing keys.
>
> So I doubt requiring signed requests is common.
>
> --
> marko
>



Re: Add libtls functionality for OCSP, and OCSP stapling support

2016-07-08 Thread Marko Kreen
On Wed, Jul 06, 2016 at 08:30:23PM +0900, kinichiro inoguchi wrote:
> Hi, I have 2 questions about this implementation.
> 
> 1) Can the OCSP client put multiple certificates to check in the request ?
>like this.
> 
> $ openssl ocsp -reqin ocsp_req.der -req_text
> OCSP Request Data:
> Version: 1 (0x0)
> Requestor List:
> Certificate ID:
>   Hash Algorithm: sha1
>   Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
>   Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
>   Serial Number: 03
> Certificate ID:
>   Hash Algorithm: sha1
>   Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
>   Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
>   Serial Number: D0F00ED53778C7C5
> Request Extensions:
> OCSP Nonce:
> 04104C65A6FA1D4839916C3B8C18A4EF2E5D
> 

No.  Current goal is to get stapling working, which deals with
one cert at a time.

Requesting multiple certs with one request seems dubious even
in general (rfc6961) case as each cert may potentially have
different responder.  The API needs to export multiple
(ocsp_url, request_blob) pairs then.  But there is option
to embed multiple certs into one request_blob if they
use same responder, as optimization.

> 2) Is it available signing to OCSP request by client ?
>I indicate this https://tools.ietf.org/html/rfc6960#section-4.1.2
>"The requestor MAY choose to sign the OCSP request."
> 
> These 2 functionality might NOT need when we're doing OCSP stapling.
> (server cert to verify by OCSP stapling will be always single ...)

No.  It's possible to expose it as option, but why?

Btw, I tried to use OCSP_request_add1_nonce() to add unique nonce to
reqests, for replay protection.  Common OCSP responders reject such
requests.  I guess both on performace and security grounds,
to have dumb responders that do not have access to signing keys.

So I doubt requiring signed requests is common.

-- 
marko



Re: Add libtls functionality for OCSP, and OCSP stapling support

2016-07-06 Thread kinichiro inoguchi
Hi, I have 2 questions about this implementation.

1) Can the OCSP client put multiple certificates to check in the request ?
   like this.

$ openssl ocsp -reqin ocsp_req.der -req_text
OCSP Request Data:
Version: 1 (0x0)
Requestor List:
Certificate ID:
  Hash Algorithm: sha1
  Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
  Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
  Serial Number: 03
Certificate ID:
  Hash Algorithm: sha1
  Issuer Name Hash: 3429CF3BC59A76F61C3296E597B1F9D5F4A52B3A
  Issuer Key Hash: 68DBFBB578936A6704433C981F7ECE61819838C7
  Serial Number: D0F00ED53778C7C5
Request Extensions:
OCSP Nonce:
04104C65A6FA1D4839916C3B8C18A4EF2E5D


2) Is it available signing to OCSP request by client ?
   I indicate this https://tools.ietf.org/html/rfc6960#section-4.1.2
   "The requestor MAY choose to sign the OCSP request."

These 2 functionality might NOT need when we're doing OCSP stapling.
(server cert to verify by OCSP stapling will be always single ...)

Best regards,

Kinichiro Inoguchi



Add libtls functionality for OCSP, and OCSP stapling support

2016-07-05 Thread Bob Beck
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:

$ ./oc amazon.com
libssl: LibreSSL 2.4.1
OCSP stapling: good
  req_status=0 cert_status=0 crl_reason=0
  this update: Mon Jul  4 08:17:21 2016
  next update: Mon Jul 11 08:17:21 2016
  revocation: --
OCSP URL: http://ss.symcd.com
OCSP responder: good
  req_status=0 cert_status=0 crl_reason=0
  this update: Mon Jul  4 08:17:21 2016
  next update: Mon Jul 11 08:17:21 2016
  revocation: --
$ ./oc google.com
libssl: LibreSSL 2.4.1
OCSP stapling: no-ocsp
OCSP URL: http://clients1.google.com/ocsp
OCSP responder: good
  req_status=0 cert_status=0 crl_reason=0
  this update: Tue Jul  5 13:00:28 2016
  next update: Tue Jul 12 13:00:28 2016
  revocation: --
$ 

Discussion, OK's

diff --git lib/libtls/Makefile lib/libtls/Makefile
index ca2f00b..461bf44 100644
--- lib/libtls/Makefile
+++ lib/libtls/Makefile
@@ -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
diff --git lib/libtls/tls.c lib/libtls/tls.c
index 76d00e5..b00bea8 100644
--- lib/libtls/tls.c
+++ lib/libtls/tls.c
@@ -393,6 +393,13 @@ tls_reset(struct tls *ctx)
tls_free_conninfo(ctx->conninfo);
free(ctx->conninfo);
ctx->conninfo = NULL;
+
+   tls_ocsp_info_free(ctx->ocsp_info);
+   ctx->ocsp_info = NULL;
+   ctx->ocsp_result = NULL;
+
+   if (ctx->flags & TLS_OCSP_CLIENT)
+   tls_ocsp_client_free(ctx);
 }
 
 int
diff --git lib/libtls/tls.h lib/libtls/tls.h
index 75c46c1..da6cd69 100644
--- lib/libtls/tls.h
+++ lib/libtls/tls.h
@@ -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_MALFORMED1
+#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_HOLD6
+#define TLS_CRL_REASON_REMOVE_FROM_CRL 8
+#define TLS_CRL_REASON_PRIVILEGE_WITH_DRAWN9
+#define TLS_CRL_REASON_AA_COMPROMISE   10
 
 struct tls;
 struct tls_config;
@@ -70,6 +93,8 @@ int tls_config_set_keypair_file(struct tls_config *_config,
 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);
 
@@ -121,6 +146,18 @@ const char *tls_conn_cipher(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
 }
 #endif
diff --git lib/libtls/tls_client.c lib/libtls/tls_client.c
index 3847f4c..86dd9a8