summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2016-08-01 17:32:19 +0000
committerjsing <>2016-08-01 17:32:19 +0000
commitb75dcc327d73d0f5f00f1367a7d98e3979ddbd9f (patch)
treee03f60ab444ada6f737a380e17e8eba68f90a817
parenta37dd8e8e7691f9cc5b065e47b95a2c75eb96512 (diff)
downloadopenbsd-b75dcc327d73d0f5f00f1367a7d98e3979ddbd9f.tar.gz
openbsd-b75dcc327d73d0f5f00f1367a7d98e3979ddbd9f.tar.bz2
openbsd-b75dcc327d73d0f5f00f1367a7d98e3979ddbd9f.zip
Add ALPN support to libtls.
ok beck@ doug@
-rw-r--r--src/lib/libtls/tls.c10
-rw-r--r--src/lib/libtls/tls.h6
-rw-r--r--src/lib/libtls/tls_config.c70
-rw-r--r--src/lib/libtls/tls_conninfo.c35
-rw-r--r--src/lib/libtls/tls_init.336
-rw-r--r--src/lib/libtls/tls_internal.h6
-rw-r--r--src/lib/libtls/tls_server.c20
7 files changed, 168 insertions, 15 deletions
diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c
index 857b8d0811..2584ceb88b 100644
--- a/src/lib/libtls/tls.c
+++ b/src/lib/libtls/tls.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls.c,v 1.41 2016/07/07 14:09:03 jsing Exp $ */ 1/* $OpenBSD: tls.c,v 1.42 2016/08/01 17:32:19 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -310,6 +310,14 @@ tls_configure_ssl(struct tls *ctx)
310 if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0) 310 if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0)
311 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1_2); 311 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1_2);
312 312
313 if (ctx->config->alpn != NULL) {
314 if (SSL_CTX_set_alpn_protos(ctx->ssl_ctx, ctx->config->alpn,
315 ctx->config->alpn_len) != 0) {
316 tls_set_errorx(ctx, "failed to set alpn");
317 goto err;
318 }
319 }
320
313 if (ctx->config->ciphers != NULL) { 321 if (ctx->config->ciphers != NULL) {
314 if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, 322 if (SSL_CTX_set_cipher_list(ctx->ssl_ctx,
315 ctx->config->ciphers) != 1) { 323 ctx->config->ciphers) != 1) {
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h
index 75c46c1a1a..a29030d8d9 100644
--- a/src/lib/libtls/tls.h
+++ b/src/lib/libtls/tls.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls.h,v 1.29 2016/05/27 14:21:24 jsing Exp $ */ 1/* $OpenBSD: tls.h,v 1.30 2016/08/01 17:32:19 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -52,6 +52,7 @@ const char *tls_error(struct tls *_ctx);
52struct tls_config *tls_config_new(void); 52struct tls_config *tls_config_new(void);
53void tls_config_free(struct tls_config *_config); 53void tls_config_free(struct tls_config *_config);
54 54
55int tls_config_set_alpn(struct tls_config *_config, const char *_alpn);
55int tls_config_set_ca_file(struct tls_config *_config, const char *_ca_file); 56int tls_config_set_ca_file(struct tls_config *_config, const char *_ca_file);
56int tls_config_set_ca_path(struct tls_config *_config, const char *_ca_path); 57int tls_config_set_ca_path(struct tls_config *_config, const char *_ca_path);
57int tls_config_set_ca_mem(struct tls_config *_config, const uint8_t *_ca, 58int tls_config_set_ca_mem(struct tls_config *_config, const uint8_t *_ca,
@@ -116,8 +117,9 @@ const char *tls_peer_cert_subject(struct tls *_ctx);
116time_t tls_peer_cert_notbefore(struct tls *_ctx); 117time_t tls_peer_cert_notbefore(struct tls *_ctx);
117time_t tls_peer_cert_notafter(struct tls *_ctx); 118time_t tls_peer_cert_notafter(struct tls *_ctx);
118 119
119const char *tls_conn_version(struct tls *_ctx); 120const char *tls_conn_alpn_selected(struct tls *_ctx);
120const char *tls_conn_cipher(struct tls *_ctx); 121const char *tls_conn_cipher(struct tls *_ctx);
122const char *tls_conn_version(struct tls *_ctx);
121 123
122uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); 124uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password);
123 125
diff --git a/src/lib/libtls/tls_config.c b/src/lib/libtls/tls_config.c
index 43f06b0063..640a69e783 100644
--- a/src/lib/libtls/tls_config.c
+++ b/src/lib/libtls/tls_config.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_config.c,v 1.22 2016/07/13 16:30:48 jsing Exp $ */ 1/* $OpenBSD: tls_config.c,v 1.23 2016/08/01 17:32:19 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -166,6 +166,7 @@ tls_config_free(struct tls_config *config)
166 166
167 free(config->error.msg); 167 free(config->error.msg);
168 168
169 free(config->alpn);
169 free((char *)config->ca_file); 170 free((char *)config->ca_file);
170 free((char *)config->ca_mem); 171 free((char *)config->ca_mem);
171 free((char *)config->ca_path); 172 free((char *)config->ca_path);
@@ -249,6 +250,73 @@ tls_config_parse_protocols(uint32_t *protocols, const char *protostr)
249 return (0); 250 return (0);
250} 251}
251 252
253static int
254tls_config_parse_alpn(struct tls_config *config, const char *alpn,
255 char **alpn_data, size_t *alpn_len)
256{
257 size_t buf_len, i, len;
258 char *buf = NULL;
259 char *s = NULL;
260 char *p, *q;
261
262 free(*alpn_data);
263 *alpn_data = NULL;
264 *alpn_len = 0;
265
266 if ((buf_len = strlen(alpn) + 1) > 65535) {
267 tls_config_set_errorx(config, "alpn too large");
268 goto err;
269 }
270
271 if ((buf = malloc(buf_len)) == NULL) {
272 tls_config_set_errorx(config, "out of memory");
273 goto err;
274 }
275
276 if ((s = strdup(alpn)) == NULL) {
277 tls_config_set_errorx(config, "out of memory");
278 goto err;
279 }
280
281 i = 0;
282 q = s;
283 while ((p = strsep(&q, ",")) != NULL) {
284 if ((len = strlen(p)) == 0) {
285 tls_config_set_errorx(config,
286 "alpn protocol with zero length");
287 goto err;
288 }
289 if (len > 255) {
290 tls_config_set_errorx(config,
291 "alpn protocol too long");
292 goto err;
293 }
294 buf[i++] = len & 0xff;
295 memcpy(&buf[i], p, len);
296 i += len;
297 }
298
299 free(s);
300
301 *alpn_data = buf;
302 *alpn_len = buf_len;
303
304 return (0);
305
306 err:
307 free(buf);
308 free(s);
309
310 return (-1);
311}
312
313int
314tls_config_set_alpn(struct tls_config *config, const char *alpn)
315{
316 return tls_config_parse_alpn(config, alpn, &config->alpn,
317 &config->alpn_len);
318}
319
252int 320int
253tls_config_set_ca_file(struct tls_config *config, const char *ca_file) 321tls_config_set_ca_file(struct tls_config *config, const char *ca_file)
254{ 322{
diff --git a/src/lib/libtls/tls_conninfo.c b/src/lib/libtls/tls_conninfo.c
index 1e134bfe59..93526fceeb 100644
--- a/src/lib/libtls/tls_conninfo.c
+++ b/src/lib/libtls/tls_conninfo.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_conninfo.c,v 1.5 2015/10/07 23:33:38 beck Exp $ */ 1/* $OpenBSD: tls_conninfo.c,v 1.6 2016/08/01 17:32:19 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org> 4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
@@ -150,6 +150,26 @@ tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, time_t *notafter)
150 return (rv); 150 return (rv);
151} 151}
152 152
153static int
154tls_conninfo_alpn_proto(struct tls *ctx)
155{
156 const unsigned char *p;
157 unsigned int len;
158
159 free(ctx->conninfo->alpn);
160 ctx->conninfo->alpn = NULL;
161
162 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len);
163 if (len > 0) {
164 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL)
165 return (-1);
166 memcpy(ctx->conninfo->alpn, p, len);
167 ctx->conninfo->alpn[len] = '\0';
168 }
169
170 return (0);
171}
172
153int 173int
154tls_get_conninfo(struct tls *ctx) { 174tls_get_conninfo(struct tls *ctx) {
155 const char * tmp; 175 const char * tmp;
@@ -175,6 +195,9 @@ tls_get_conninfo(struct tls *ctx) {
175 ctx->conninfo->cipher = strdup(tmp); 195 ctx->conninfo->cipher = strdup(tmp);
176 if (ctx->conninfo->cipher == NULL) 196 if (ctx->conninfo->cipher == NULL)
177 goto err; 197 goto err;
198 if (tls_conninfo_alpn_proto(ctx) == -1)
199 goto err;
200
178 return (0); 201 return (0);
179err: 202err:
180 tls_free_conninfo(ctx->conninfo); 203 tls_free_conninfo(ctx->conninfo);
@@ -184,6 +207,8 @@ err:
184void 207void
185tls_free_conninfo(struct tls_conninfo *conninfo) { 208tls_free_conninfo(struct tls_conninfo *conninfo) {
186 if (conninfo != NULL) { 209 if (conninfo != NULL) {
210 free(conninfo->alpn);
211 conninfo->alpn = NULL;
187 free(conninfo->hash); 212 free(conninfo->hash);
188 conninfo->hash = NULL; 213 conninfo->hash = NULL;
189 free(conninfo->subject); 214 free(conninfo->subject);
@@ -198,6 +223,14 @@ tls_free_conninfo(struct tls_conninfo *conninfo) {
198} 223}
199 224
200const char * 225const char *
226tls_conn_alpn_selected(struct tls *ctx)
227{
228 if (ctx->conninfo == NULL)
229 return (NULL);
230 return (ctx->conninfo->alpn);
231}
232
233const char *
201tls_conn_cipher(struct tls *ctx) 234tls_conn_cipher(struct tls *ctx)
202{ 235{
203 if (ctx->conninfo == NULL) 236 if (ctx->conninfo == NULL)
diff --git a/src/lib/libtls/tls_init.3 b/src/lib/libtls/tls_init.3
index b4c6a7cc3a..0969c093a1 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.62 2016/07/13 16:30:48 jsing Exp $ 1.\" $OpenBSD: tls_init.3,v 1.63 2016/08/01 17:32:19 jsing 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: July 13 2016 $ 17.Dd $Mdocdate: August 1 2016 $
18.Dt TLS_INIT 3 18.Dt TLS_INIT 3
19.Os 19.Os
20.Sh NAME 20.Sh NAME
@@ -24,6 +24,7 @@
24.Nm tls_config_new , 24.Nm tls_config_new ,
25.Nm tls_config_free , 25.Nm tls_config_free ,
26.Nm tls_config_parse_protocols , 26.Nm tls_config_parse_protocols ,
27.Nm tls_config_set_alpn ,
27.Nm tls_config_set_ca_file , 28.Nm tls_config_set_ca_file ,
28.Nm tls_config_set_ca_path , 29.Nm tls_config_set_ca_path ,
29.Nm tls_config_set_ca_mem , 30.Nm tls_config_set_ca_mem ,
@@ -54,8 +55,9 @@
54.Nm tls_peer_cert_hash , 55.Nm tls_peer_cert_hash ,
55.Nm tls_peer_cert_notbefore , 56.Nm tls_peer_cert_notbefore ,
56.Nm tls_peer_cert_notafter , 57.Nm tls_peer_cert_notafter ,
57.Nm tls_conn_version , 58.Nm tls_conn_alpn_selected ,
58.Nm tls_conn_cipher , 59.Nm tls_conn_cipher ,
60.Nm tls_conn_version ,
59.Nm tls_load_file , 61.Nm tls_load_file ,
60.Nm tls_client , 62.Nm tls_client ,
61.Nm tls_server , 63.Nm tls_server ,
@@ -88,6 +90,8 @@
88.Ft "int" 90.Ft "int"
89.Fn tls_config_parse_protocols "uint32_t *protocols" "const char *protostr" 91.Fn tls_config_parse_protocols "uint32_t *protocols" "const char *protostr"
90.Ft "int" 92.Ft "int"
93.Fn tls_config_set_alpn "struct tls_config *config" "const char *alpn"
94.Ft "int"
91.Fn tls_config_set_ca_file "struct tls_config *config" "const char *ca_file" 95.Fn tls_config_set_ca_file "struct tls_config *config" "const char *ca_file"
92.Ft "int" 96.Ft "int"
93.Fn tls_config_set_ca_path "struct tls_config *config" "const char *ca_path" 97.Fn tls_config_set_ca_path "struct tls_config *config" "const char *ca_path"
@@ -148,9 +152,11 @@
148.Ft "time_t" 152.Ft "time_t"
149.Fn tls_peer_cert_notafter "struct tls *ctx" 153.Fn tls_peer_cert_notafter "struct tls *ctx"
150.Ft "const char *" 154.Ft "const char *"
151.Fn tls_conn_version "struct tls *ctx" 155.Fn tls_conn_alpn_selected "struct tls *ctx"
152.Ft "const char *" 156.Ft "const char *"
153.Fn tls_conn_cipher "struct tls *ctx" 157.Fn tls_conn_cipher "struct tls *ctx"
158.Ft "const char *"
159.Fn tls_conn_version "struct tls *ctx"
154.Ft "uint8_t *" 160.Ft "uint8_t *"
155.Fn tls_load_file "const char *file" "size_t *len" "char *password" 161.Fn tls_load_file "const char *file" "size_t *len" "char *password"
156.Ft "struct tls *" 162.Ft "struct tls *"
@@ -295,6 +301,11 @@ The following functions modify a configuration by setting parameters.
295Configuration options may apply to only clients or only servers or both. 301Configuration options may apply to only clients or only servers or both.
296.Bl -bullet -offset four 302.Bl -bullet -offset four
297.It 303.It
304.Fn tls_config_set_alpn
305sets the ALPN protocols that are supported.
306The alpn string is a comma separated list of protocols, in order of preference.
307.Em (Client and Server)
308.It
298.Fn tls_config_set_ca_file 309.Fn tls_config_set_ca_file
299sets the filename used to load a file 310sets the filename used to load a file
300containing the root certificates. 311containing the root certificates.
@@ -480,13 +491,14 @@ the peer certificate from
480will only succeed after the handshake is complete. 491will only succeed after the handshake is complete.
481.Em (Server and client) 492.Em (Server and client)
482.It 493.It
483.Fn tls_conn_version 494.Fn tls_conn_alpn_selected
484returns a string 495returns a string that specifies the ALPN protocol selected for use with the peer
485corresponding to a TLS version negotiated with the peer
486connected to 496connected to
487.Ar ctx . 497.Ar ctx .
488.Fn tls_conn_version 498If no protocol was selected then NULL is returned.
499.Fn tls_conn_alpn_selected
489will only succeed after the handshake is complete. 500will only succeed after the handshake is complete.
501.Em (Server and Client)
490.It 502.It
491.Fn tls_conn_cipher 503.Fn tls_conn_cipher
492returns a string 504returns a string
@@ -497,6 +509,14 @@ connected to
497will only succeed after the handshake is complete. 509will only succeed after the handshake is complete.
498.Em (Server and client) 510.Em (Server and client)
499.It 511.It
512.Fn tls_conn_version
513returns a string
514corresponding to a TLS version negotiated with the peer
515connected to
516.Ar ctx .
517.Fn tls_conn_version
518will only succeed after the handshake is complete.
519.It
500.Fn tls_load_file 520.Fn tls_load_file
501loads a certificate or key from disk into memory to be loaded with 521loads a certificate or key from disk into memory to be loaded with
502.Fn tls_config_set_ca_mem , 522.Fn tls_config_set_ca_mem ,
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h
index 6c56e6fb84..17358429c7 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.32 2016/07/13 16:30:48 jsing Exp $ */ 1/* $OpenBSD: tls_internal.h,v 1.33 2016/08/01 17:32:19 jsing 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>
@@ -55,6 +55,8 @@ struct tls_keypair {
55struct tls_config { 55struct tls_config {
56 struct tls_error error; 56 struct tls_error error;
57 57
58 char *alpn;
59 size_t alpn_len;
58 const char *ca_file; 60 const char *ca_file;
59 const char *ca_path; 61 const char *ca_path;
60 char *ca_mem; 62 char *ca_mem;
@@ -73,6 +75,7 @@ struct tls_config {
73}; 75};
74 76
75struct tls_conninfo { 77struct tls_conninfo {
78 char *alpn;
76 char *issuer; 79 char *issuer;
77 char *subject; 80 char *subject;
78 char *hash; 81 char *hash;
@@ -104,6 +107,7 @@ struct tls {
104 SSL *ssl_conn; 107 SSL *ssl_conn;
105 SSL_CTX *ssl_ctx; 108 SSL_CTX *ssl_ctx;
106 X509 *ssl_peer_cert; 109 X509 *ssl_peer_cert;
110
107 struct tls_conninfo *conninfo; 111 struct tls_conninfo *conninfo;
108}; 112};
109 113
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c
index 1d94c99bc0..f13c9db083 100644
--- a/src/lib/libtls/tls_server.c
+++ b/src/lib/libtls/tls_server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_server.c,v 1.19 2016/04/28 17:05:59 jsing Exp $ */ 1/* $OpenBSD: tls_server.c,v 1.20 2016/08/01 17:32:19 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -48,6 +48,20 @@ tls_server_conn(struct tls *ctx)
48 return (conn_ctx); 48 return (conn_ctx);
49} 49}
50 50
51static int
52tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
53 const unsigned char *in, unsigned int inlen, void *arg)
54{
55 struct tls *ctx = arg;
56
57 if (SSL_select_next_proto((unsigned char**)out, outlen,
58 ctx->config->alpn, ctx->config->alpn_len, in, inlen) ==
59 OPENSSL_NPN_NEGOTIATED)
60 return (SSL_TLSEXT_ERR_OK);
61
62 return (SSL_TLSEXT_ERR_NOACK);
63}
64
51int 65int
52tls_configure_server(struct tls *ctx) 66tls_configure_server(struct tls *ctx)
53{ 67{
@@ -71,6 +85,10 @@ tls_configure_server(struct tls *ctx)
71 goto err; 85 goto err;
72 } 86 }
73 87
88 if (ctx->config->alpn != NULL)
89 SSL_CTX_set_alpn_select_cb(ctx->ssl_ctx, tls_server_alpn_cb,
90 ctx);
91
74 if (ctx->config->dheparams == -1) 92 if (ctx->config->dheparams == -1)
75 SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1); 93 SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1);
76 else if (ctx->config->dheparams == 1024) 94 else if (ctx->config->dheparams == 1024)