| OLD | NEW |
| (Empty) |
| 1 commit ed5845e49b3c76f8735ec00e151a7b234acc266c | |
| 2 Author: Adam Langley <agl@chromium.org> | |
| 3 Date: Thu Nov 4 16:06:58 2010 -0400 | |
| 4 | |
| 5 next_proto_neg.patch | |
| 6 | |
| 7 diff --git a/apps/apps.c b/apps/apps.c | |
| 8 index ab60b70..eede8a8 100644 | |
| 9 --- a/apps/apps.c | |
| 10 +++ b/apps/apps.c | |
| 11 @@ -2579,3 +2579,45 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *s
ecret) | |
| 12 } | |
| 13 | |
| 14 #endif | |
| 15 + | |
| 16 +/* next_protos_parse parses a comma separated list of strings into a string | |
| 17 + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. | |
| 18 + * outlen: (output) set to the length of the resulting buffer on success. | |
| 19 + * err: (maybe NULL) on failure, an error message line is written to this BIO
. | |
| 20 + * in: a NUL termianted string like "abc,def,ghi" | |
| 21 + * | |
| 22 + * returns: a malloced buffer | |
| 23 + */ | |
| 24 +unsigned char *next_protos_parse(unsigned short *outlen, const char *in) | |
| 25 + { | |
| 26 + size_t len; | |
| 27 + unsigned char *out; | |
| 28 + size_t i, start = 0; | |
| 29 + | |
| 30 + len = strlen(in); | |
| 31 + if (len > 65535) | |
| 32 + return NULL; | |
| 33 + | |
| 34 + out = OPENSSL_malloc(strlen(in) + 1); | |
| 35 + if (!out) | |
| 36 + return NULL; | |
| 37 + | |
| 38 + for (i = 0; i <= len; ++i) | |
| 39 + { | |
| 40 + if (i == len || in[i] == ',') | |
| 41 + { | |
| 42 + if (i - start > 255) | |
| 43 + { | |
| 44 + OPENSSL_free(out); | |
| 45 + return NULL; | |
| 46 + } | |
| 47 + out[start] = i - start; | |
| 48 + start = i + 1; | |
| 49 + } | |
| 50 + else | |
| 51 + out[i+1] = in[i]; | |
| 52 + } | |
| 53 + | |
| 54 + *outlen = len + 1; | |
| 55 + return out; | |
| 56 + } | |
| 57 diff --git a/apps/s_apps.h b/apps/s_apps.h | |
| 58 index f5a39ba..513bcfe 100644 | |
| 59 --- a/apps/s_apps.h | |
| 60 +++ b/apps/s_apps.h | |
| 61 @@ -174,3 +174,5 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int ty
pe, | |
| 62 | |
| 63 int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, unsig
ned int *cookie_len); | |
| 64 int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, unsigne
d int cookie_len); | |
| 65 + | |
| 66 +unsigned char *next_protos_parse(unsigned short *outlen, const char *in); | |
| 67 diff --git a/apps/s_client.c b/apps/s_client.c | |
| 68 index c071658..6033e77 100644 | |
| 69 --- a/apps/s_client.c | |
| 70 +++ b/apps/s_client.c | |
| 71 @@ -249,6 +249,7 @@ static void sc_usage(void) | |
| 72 BIO_printf(bio_err," -status - request certificate status from
server\n"); | |
| 73 BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis sessi
on tickets\n"); | |
| 74 BIO_printf(bio_err," -cutthrough - enable 1-RTT full-handshake for
strong ciphers\n"); | |
| 75 + BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, consideri
ng named protocols supported (comma-separated list)\n"); | |
| 76 #endif | |
| 77 BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renego
tiation (dangerous)\n"); | |
| 78 } | |
| 79 @@ -284,6 +285,38 @@ enum | |
| 80 PROTO_XMPP | |
| 81 }; | |
| 82 | |
| 83 +/* This the context that we pass to next_proto_cb */ | |
| 84 +typedef struct tlsextnextprotoctx_st { | |
| 85 + unsigned char *data; | |
| 86 + unsigned short len; | |
| 87 + int status; | |
| 88 +} tlsextnextprotoctx; | |
| 89 + | |
| 90 +static tlsextnextprotoctx next_proto; | |
| 91 + | |
| 92 +static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, co
nst unsigned char *in, unsigned int inlen, void *arg) | |
| 93 + { | |
| 94 + tlsextnextprotoctx *ctx = arg; | |
| 95 + | |
| 96 + if (!c_quiet) | |
| 97 + { | |
| 98 + /* We can assume that |in| is syntactically valid. */ | |
| 99 + unsigned i; | |
| 100 + BIO_printf(bio_c_out, "Protocols advertised by server: "); | |
| 101 + for (i = 0; i < inlen; ) | |
| 102 + { | |
| 103 + if (i) | |
| 104 + BIO_write(bio_c_out, ", ", 2); | |
| 105 + BIO_write(bio_c_out, &in[i + 1], in[i]); | |
| 106 + i += in[i] + 1; | |
| 107 + } | |
| 108 + BIO_write(bio_c_out, "\n", 1); | |
| 109 + } | |
| 110 + | |
| 111 + ctx->status = SSL_select_next_proto(out, outlen, in, inlen, ctx->data, c
tx->len); | |
| 112 + return SSL_TLSEXT_ERR_OK; | |
| 113 + } | |
| 114 + | |
| 115 int MAIN(int, char **); | |
| 116 | |
| 117 int MAIN(int argc, char **argv) | |
| 118 @@ -336,6 +369,7 @@ int MAIN(int argc, char **argv) | |
| 119 char *servername = NULL; | |
| 120 tlsextctx tlsextcbp = | |
| 121 {NULL,0}; | |
| 122 + const char *next_proto_neg_in = NULL; | |
| 123 #endif | |
| 124 char *sess_in = NULL; | |
| 125 char *sess_out = NULL; | |
| 126 @@ -536,6 +570,11 @@ int MAIN(int argc, char **argv) | |
| 127 #ifndef OPENSSL_NO_TLSEXT | |
| 128 else if (strcmp(*argv,"-no_ticket") == 0) | |
| 129 { off|=SSL_OP_NO_TICKET; } | |
| 130 + else if (strcmp(*argv,"-nextprotoneg") == 0) | |
| 131 + { | |
| 132 + if (--argc < 1) goto bad; | |
| 133 + next_proto_neg_in = *(++argv); | |
| 134 + } | |
| 135 #endif | |
| 136 else if (strcmp(*argv,"-cutthrough") == 0) | |
| 137 cutthrough=1; | |
| 138 @@ -624,6 +663,21 @@ bad: | |
| 139 OpenSSL_add_ssl_algorithms(); | |
| 140 SSL_load_error_strings(); | |
| 141 | |
| 142 +#ifndef OPENSSL_NO_TLSEXT | |
| 143 + next_proto.status = -1; | |
| 144 + if (next_proto_neg_in) | |
| 145 + { | |
| 146 + next_proto.data = next_protos_parse(&next_proto.len, next_proto_
neg_in); | |
| 147 + if (next_proto.data == NULL) | |
| 148 + { | |
| 149 + BIO_printf(bio_err, "Error parsing -nextprotoneg argumen
t\n"); | |
| 150 + goto end; | |
| 151 + } | |
| 152 + } | |
| 153 + else | |
| 154 + next_proto.data = NULL; | |
| 155 +#endif | |
| 156 + | |
| 157 #ifndef OPENSSL_NO_ENGINE | |
| 158 e = setup_engine(bio_err, engine_id, 1); | |
| 159 if (ssl_client_engine_id) | |
| 160 @@ -738,6 +792,9 @@ bad: | |
| 161 SSL_CTX_set_mode(ctx, ssl_mode); | |
| 162 } | |
| 163 | |
| 164 + if (next_proto.data) | |
| 165 + SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto
); | |
| 166 + | |
| 167 if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); | |
| 168 if (cipher != NULL) | |
| 169 if(!SSL_CTX_set_cipher_list(ctx,cipher)) { | |
| 170 @@ -1555,6 +1612,20 @@ static void print_stuff(BIO *bio, SSL *s, int full) | |
| 171 BIO_printf(bio,"Expansion: %s\n", | |
| 172 expansion ? SSL_COMP_get_name(expansion) : "NONE"); | |
| 173 #endif | |
| 174 + | |
| 175 +#ifndef OPENSSL_NO_TLSEXT | |
| 176 + { | |
| 177 + if (next_proto.status != -1) { | |
| 178 + const unsigned char *proto; | |
| 179 + unsigned int proto_len; | |
| 180 + SSL_get0_next_proto_negotiated(s, &proto, &proto_len); | |
| 181 + BIO_printf(bio, "Next protocol: (%d) ", next_proto.statu
s); | |
| 182 + BIO_write(bio, proto, proto_len); | |
| 183 + BIO_write(bio, "\n", 1); | |
| 184 + } | |
| 185 + } | |
| 186 +#endif | |
| 187 + | |
| 188 SSL_SESSION_print(bio,SSL_get_session(s)); | |
| 189 BIO_printf(bio,"---\n"); | |
| 190 if (peer != NULL) | |
| 191 diff --git a/apps/s_server.c b/apps/s_server.c | |
| 192 index 88b308c..c4e19c9 100644 | |
| 193 --- a/apps/s_server.c | |
| 194 +++ b/apps/s_server.c | |
| 195 @@ -405,6 +405,7 @@ static void sv_usage(void) | |
| 196 BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions rece
ived\n"); | |
| 197 BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session t
ickets\n"); | |
| 198 BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renego
tiation (dangerous)\n"); | |
| 199 + BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols fo
r the NPN extension (comma-separated list)\n"); | |
| 200 #endif | |
| 201 } | |
| 202 | |
| 203 @@ -740,6 +741,26 @@ BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_R
ESPID_num(ids)); | |
| 204 goto done; | |
| 205 } | |
| 206 #endif | |
| 207 + | |
| 208 + | |
| 209 +/* This the context that we pass to next_proto_cb */ | |
| 210 +typedef struct tlsextnextprotoctx_st { | |
| 211 + unsigned char *data; | |
| 212 + unsigned int len; | |
| 213 +} tlsextnextprotoctx; | |
| 214 + | |
| 215 + | |
| 216 +static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) | |
| 217 + { | |
| 218 + tlsextnextprotoctx *next_proto = arg; | |
| 219 + | |
| 220 + *data = next_proto->data; | |
| 221 + *len = next_proto->len; | |
| 222 + | |
| 223 + return SSL_TLSEXT_ERR_OK; | |
| 224 + } | |
| 225 + | |
| 226 + | |
| 227 int MAIN(int, char **); | |
| 228 | |
| 229 #ifndef OPENSSL_NO_JPAKE | |
| 230 @@ -779,6 +800,8 @@ int MAIN(int argc, char *argv[]) | |
| 231 #endif | |
| 232 #ifndef OPENSSL_NO_TLSEXT | |
| 233 tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING}; | |
| 234 + const char *next_proto_neg_in = NULL; | |
| 235 + tlsextnextprotoctx next_proto; | |
| 236 #endif | |
| 237 | |
| 238 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) | |
| 239 @@ -1077,7 +1100,11 @@ int MAIN(int argc, char *argv[]) | |
| 240 if (--argc < 1) goto bad; | |
| 241 s_key_file2= *(++argv); | |
| 242 } | |
| 243 - | |
| 244 + else if (strcmp(*argv,"-nextprotoneg") == 0) | |
| 245 + { | |
| 246 + if (--argc < 1) goto bad; | |
| 247 + next_proto_neg_in = *(++argv); | |
| 248 + } | |
| 249 #endif | |
| 250 #ifndef OPENSSL_NO_JPAKE | |
| 251 else if (strcmp(*argv,"-jpake") == 0) | |
| 252 @@ -1162,6 +1189,20 @@ bad: | |
| 253 goto end; | |
| 254 } | |
| 255 } | |
| 256 + | |
| 257 + if (next_proto_neg_in) | |
| 258 + { | |
| 259 + unsigned short len; | |
| 260 + next_proto.data = next_protos_parse(&len, | |
| 261 + next_proto_neg_in); | |
| 262 + if (next_proto.data == NULL) | |
| 263 + goto end; | |
| 264 + next_proto.len = len; | |
| 265 + } | |
| 266 + else | |
| 267 + { | |
| 268 + next_proto.data = NULL; | |
| 269 + } | |
| 270 #endif | |
| 271 } | |
| 272 if (s_dcert_file) | |
| 273 @@ -1341,6 +1382,11 @@ bad: | |
| 274 store = SSL_CTX_get_cert_store(ctx2); | |
| 275 X509_STORE_set_flags(store, vflags); | |
| 276 } | |
| 277 + | |
| 278 + if (next_proto.data) | |
| 279 + { | |
| 280 + SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_
proto); | |
| 281 + } | |
| 282 #endif | |
| 283 | |
| 284 | |
| 285 @@ -1980,6 +2026,10 @@ static int init_ssl_connection(SSL *con) | |
| 286 X509 *peer; | |
| 287 long verify_error; | |
| 288 MS_STATIC char buf[BUFSIZ]; | |
| 289 +#ifndef OPENSSL_NO_TLSEXT | |
| 290 + const unsigned char *next_proto_neg; | |
| 291 + unsigned next_proto_neg_len; | |
| 292 +#endif | |
| 293 | |
| 294 if ((i=SSL_accept(con)) <= 0) | |
| 295 { | |
| 296 @@ -2019,6 +2069,14 @@ static int init_ssl_connection(SSL *con) | |
| 297 BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf); | |
| 298 str=SSL_CIPHER_get_name(SSL_get_current_cipher(con)); | |
| 299 BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)"); | |
| 300 +#ifndef OPENSSL_NO_TLSEXT | |
| 301 + SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len
); | |
| 302 + if (next_proto_neg) { | |
| 303 + BIO_printf(bio_s_out,"NEXTPROTO is "); | |
| 304 + BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len); | |
| 305 + BIO_printf(bio_s_out, "\n"); | |
| 306 + } | |
| 307 +#endif | |
| 308 if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n"); | |
| 309 if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) & | |
| 310 TLS1_FLAGS_TLS_PADDING_BUG) | |
| 311 diff --git a/ssl/s3_both.c b/ssl/s3_both.c | |
| 312 index 869a25d..b88288e 100644 | |
| 313 --- a/ssl/s3_both.c | |
| 314 +++ b/ssl/s3_both.c | |
| 315 @@ -204,16 +204,34 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *s
ender, int slen) | |
| 316 return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); | |
| 317 } | |
| 318 | |
| 319 +/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen t
o far. */ | |
| 320 +void ssl3_take_mac(SSL *s) { | |
| 321 + const char *sender; | |
| 322 + int slen; | |
| 323 + | |
| 324 + if (s->state & SSL_ST_CONNECT) | |
| 325 + { | |
| 326 + sender=s->method->ssl3_enc->server_finished_label; | |
| 327 + slen=s->method->ssl3_enc->server_finished_label_len; | |
| 328 + } | |
| 329 + else | |
| 330 + { | |
| 331 + sender=s->method->ssl3_enc->client_finished_label; | |
| 332 + slen=s->method->ssl3_enc->client_finished_label_len; | |
| 333 + } | |
| 334 + | |
| 335 + s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, | |
| 336 + &(s->s3->finish_dgst1), | |
| 337 + &(s->s3->finish_dgst2), | |
| 338 + sender,slen,s->s3->tmp.peer_finish_md); | |
| 339 +} | |
| 340 + | |
| 341 int ssl3_get_finished(SSL *s, int a, int b) | |
| 342 { | |
| 343 int al,i,ok; | |
| 344 long n; | |
| 345 unsigned char *p; | |
| 346 | |
| 347 - /* the mac has already been generated when we received the | |
| 348 - * change cipher spec message and is in s->s3->tmp.peer_finish_md | |
| 349 - */ | |
| 350 - | |
| 351 n=s->method->ssl_get_message(s, | |
| 352 a, | |
| 353 b, | |
| 354 @@ -516,6 +534,11 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, lon
g max, int *ok) | |
| 355 s->init_num += i; | |
| 356 n -= i; | |
| 357 } | |
| 358 + /* If receiving Finished, record MAC of prior handshake messages for | |
| 359 + * Finished verification. */ | |
| 360 + if (*s->init_buf->data == SSL3_MT_FINISHED) | |
| 361 + ssl3_take_mac(s); | |
| 362 + /* Feed this message into MAC computation. */ | |
| 363 ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); | |
| 364 if (s->msg_callback) | |
| 365 s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->d
ata, (size_t)s->init_num + 4, s, s->msg_callback_arg); | |
| 366 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c | |
| 367 index 6173dbe..f9e1554 100644 | |
| 368 --- a/ssl/s3_clnt.c | |
| 369 +++ b/ssl/s3_clnt.c | |
| 370 @@ -404,7 +404,11 @@ int ssl3_connect(SSL *s) | |
| 371 ret=ssl3_send_change_cipher_spec(s, | |
| 372 SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); | |
| 373 if (ret <= 0) goto end; | |
| 374 - s->state=SSL3_ST_CW_FINISHED_A; | |
| 375 + | |
| 376 + if (s->next_proto_negotiated) | |
| 377 + s->state=SSL3_ST_CW_NEXT_PROTO_A; | |
| 378 + else | |
| 379 + s->state=SSL3_ST_CW_FINISHED_A; | |
| 380 s->init_num=0; | |
| 381 | |
| 382 s->session->cipher=s->s3->tmp.new_cipher; | |
| 383 @@ -432,6 +436,13 @@ int ssl3_connect(SSL *s) | |
| 384 | |
| 385 break; | |
| 386 | |
| 387 + case SSL3_ST_CW_NEXT_PROTO_A: | |
| 388 + case SSL3_ST_CW_NEXT_PROTO_B: | |
| 389 + ret=ssl3_send_next_proto(s); | |
| 390 + if (ret <= 0) goto end; | |
| 391 + s->state=SSL3_ST_CW_FINISHED_A; | |
| 392 + break; | |
| 393 + | |
| 394 case SSL3_ST_CW_FINISHED_A: | |
| 395 case SSL3_ST_CW_FINISHED_B: | |
| 396 ret=ssl3_send_finished(s, | |
| 397 @@ -2752,6 +2763,30 @@ static int curve_id2nid(int curve_id) | |
| 398 } | |
| 399 #endif | |
| 400 | |
| 401 +int ssl3_send_next_proto(SSL *s) | |
| 402 + { | |
| 403 + unsigned int len, padding_len; | |
| 404 + unsigned char *d; | |
| 405 + | |
| 406 + if (s->state == SSL3_ST_CW_NEXT_PROTO_A) | |
| 407 + { | |
| 408 + len = s->next_proto_negotiated_len; | |
| 409 + padding_len = 32 - ((len + 2) % 32); | |
| 410 + d = (unsigned char *)s->init_buf->data; | |
| 411 + d[4] = len; | |
| 412 + memcpy(d + 5, s->next_proto_negotiated, len); | |
| 413 + d[5 + len] = padding_len; | |
| 414 + memset(d + 6 + len, 0, padding_len); | |
| 415 + *(d++)=SSL3_MT_NEXT_PROTO; | |
| 416 + l2n3(2 + len + padding_len, d); | |
| 417 + s->state = SSL3_ST_CW_NEXT_PROTO_B; | |
| 418 + s->init_num = 4 + 2 + len + padding_len; | |
| 419 + s->init_off = 0; | |
| 420 + } | |
| 421 + | |
| 422 + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); | |
| 423 +} | |
| 424 + | |
| 425 /* Check to see if handshake is full or resumed. Usually this is just a | |
| 426 * case of checking to see if a cache hit has occurred. In the case of | |
| 427 * session tickets we have to check the next message to be sure. | |
| 428 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c | |
| 429 index 2c44bde..84bff8d 100644 | |
| 430 --- a/ssl/s3_lib.c | |
| 431 +++ b/ssl/s3_lib.c | |
| 432 @@ -1751,6 +1751,14 @@ void ssl3_clear(SSL *s) | |
| 433 s->s3->num_renegotiations=0; | |
| 434 s->s3->in_read_app_data=0; | |
| 435 s->version=SSL3_VERSION; | |
| 436 + | |
| 437 +#ifndef OPENSSL_NO_TLSEXT | |
| 438 + if (s->next_proto_negotiated) { | |
| 439 + OPENSSL_free(s->next_proto_negotiated); | |
| 440 + s->next_proto_negotiated = 0; | |
| 441 + s->next_proto_negotiated_len = 0; | |
| 442 + } | |
| 443 +#endif | |
| 444 } | |
| 445 | |
| 446 long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) | |
| 447 diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c | |
| 448 index 5e3583c..6853058 100644 | |
| 449 --- a/ssl/s3_pkt.c | |
| 450 +++ b/ssl/s3_pkt.c | |
| 451 @@ -1264,8 +1264,6 @@ err: | |
| 452 int ssl3_do_change_cipher_spec(SSL *s) | |
| 453 { | |
| 454 int i; | |
| 455 - const char *sender; | |
| 456 - int slen; | |
| 457 | |
| 458 if (s->state & SSL_ST_ACCEPT) | |
| 459 i=SSL3_CHANGE_CIPHER_SERVER_READ; | |
| 460 @@ -1288,25 +1286,6 @@ int ssl3_do_change_cipher_spec(SSL *s) | |
| 461 if (!s->method->ssl3_enc->change_cipher_state(s,i)) | |
| 462 return(0); | |
| 463 | |
| 464 - /* we have to record the message digest at | |
| 465 - * this point so we can get it before we read | |
| 466 - * the finished message */ | |
| 467 - if (s->state & SSL_ST_CONNECT) | |
| 468 - { | |
| 469 - sender=s->method->ssl3_enc->server_finished_label; | |
| 470 - slen=s->method->ssl3_enc->server_finished_label_len; | |
| 471 - } | |
| 472 - else | |
| 473 - { | |
| 474 - sender=s->method->ssl3_enc->client_finished_label; | |
| 475 - slen=s->method->ssl3_enc->client_finished_label_len; | |
| 476 - } | |
| 477 - | |
| 478 - s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, | |
| 479 - &(s->s3->finish_dgst1), | |
| 480 - &(s->s3->finish_dgst2), | |
| 481 - sender,slen,s->s3->tmp.peer_finish_md); | |
| 482 - | |
| 483 return(1); | |
| 484 } | |
| 485 | |
| 486 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c | |
| 487 index e696450..8e0a504 100644 | |
| 488 --- a/ssl/s3_srvr.c | |
| 489 +++ b/ssl/s3_srvr.c | |
| 490 @@ -499,7 +499,10 @@ int ssl3_accept(SSL *s) | |
| 491 * a certificate, the CertificateVerify | |
| 492 * message is not sent. | |
| 493 */ | |
| 494 - s->state=SSL3_ST_SR_FINISHED_A; | |
| 495 + if (s->s3->next_proto_neg_seen) | |
| 496 + s->state=SSL3_ST_SR_NEXT_PROTO_A; | |
| 497 + else | |
| 498 + s->state=SSL3_ST_SR_FINISHED_A; | |
| 499 s->init_num = 0; | |
| 500 } | |
| 501 else | |
| 502 @@ -526,10 +529,21 @@ int ssl3_accept(SSL *s) | |
| 503 ret=ssl3_get_cert_verify(s); | |
| 504 if (ret <= 0) goto end; | |
| 505 | |
| 506 - s->state=SSL3_ST_SR_FINISHED_A; | |
| 507 + if (s->s3->next_proto_neg_seen) | |
| 508 + s->state=SSL3_ST_SR_NEXT_PROTO_A; | |
| 509 + else | |
| 510 + s->state=SSL3_ST_SR_FINISHED_A; | |
| 511 s->init_num=0; | |
| 512 break; | |
| 513 | |
| 514 + case SSL3_ST_SR_NEXT_PROTO_A: | |
| 515 + case SSL3_ST_SR_NEXT_PROTO_B: | |
| 516 + ret=ssl3_get_next_proto(s); | |
| 517 + if (ret <= 0) goto end; | |
| 518 + s->init_num = 0; | |
| 519 + s->state=SSL3_ST_SR_FINISHED_A; | |
| 520 + break; | |
| 521 + | |
| 522 case SSL3_ST_SR_FINISHED_A: | |
| 523 case SSL3_ST_SR_FINISHED_B: | |
| 524 ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, | |
| 525 @@ -597,7 +611,12 @@ int ssl3_accept(SSL *s) | |
| 526 if (ret <= 0) goto end; | |
| 527 s->state=SSL3_ST_SW_FLUSH; | |
| 528 if (s->hit) | |
| 529 - s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; | |
| 530 + { | |
| 531 + if (s->s3->next_proto_neg_seen) | |
| 532 + s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PR
OTO_A; | |
| 533 + else | |
| 534 + s->s3->tmp.next_state=SSL3_ST_SR_FINISHE
D_A; | |
| 535 + } | |
| 536 else | |
| 537 s->s3->tmp.next_state=SSL_ST_OK; | |
| 538 s->init_num=0; | |
| 539 @@ -2324,6 +2343,70 @@ err: | |
| 540 return(-1); | |
| 541 } | |
| 542 | |
| 543 +/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It | |
| 544 + * sets the next_proto member in s if found */ | |
| 545 +int ssl3_get_next_proto(SSL *s) | |
| 546 + { | |
| 547 + int ok; | |
| 548 + unsigned proto_len, padding_len; | |
| 549 + long n; | |
| 550 + const unsigned char *p; | |
| 551 + | |
| 552 + /* Clients cannot send a NextProtocol message if we didn't see the | |
| 553 + * extension in their ClientHello */ | |
| 554 + if (!s->s3->next_proto_neg_seen) { | |
| 555 + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EX
TENSION); | |
| 556 + return -1; | |
| 557 + } | |
| 558 + | |
| 559 + n=s->method->ssl_get_message(s, | |
| 560 + SSL3_ST_SR_NEXT_PROTO_A, | |
| 561 + SSL3_ST_SR_NEXT_PROTO_B, | |
| 562 + SSL3_MT_NEXT_PROTO, | |
| 563 + 129, | |
| 564 + &ok); | |
| 565 + | |
| 566 + if (!ok) | |
| 567 + return((int)n); | |
| 568 + | |
| 569 + /* s->state doesn't reflect whether ChangeCipherSpec has been received | |
| 570 + * in this handshake, but s->s3->change_cipher_spec does (will be reset | |
| 571 + * by ssl3_get_finished). */ | |
| 572 + if (!s->s3->change_cipher_spec) | |
| 573 + { | |
| 574 + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_C
CS); | |
| 575 + return -1; | |
| 576 + } | |
| 577 + | |
| 578 + if (n < 2) | |
| 579 + return 0; // The body must be > 1 bytes long */ | |
| 580 + | |
| 581 + p=(unsigned char *)s->init_msg; | |
| 582 + | |
| 583 + /* The payload looks like: | |
| 584 + * uint8 proto_len; | |
| 585 + * uint8 proto[proto_len]; | |
| 586 + * uint8 padding_len; | |
| 587 + * uint8 padding[padding_len]; | |
| 588 + */ | |
| 589 + proto_len = p[0]; | |
| 590 + if (proto_len + 2 > s->init_num) | |
| 591 + return 0; | |
| 592 + padding_len = p[proto_len + 1]; | |
| 593 + if (proto_len + padding_len + 2 != s->init_num) | |
| 594 + return 0; | |
| 595 + | |
| 596 + s->next_proto_negotiated = OPENSSL_malloc(proto_len); | |
| 597 + if (!s->next_proto_negotiated) { | |
| 598 + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE); | |
| 599 + return 0; | |
| 600 + } | |
| 601 + memcpy(s->next_proto_negotiated, p + 1, proto_len); | |
| 602 + s->next_proto_negotiated_len = proto_len; | |
| 603 + | |
| 604 + return 1; | |
| 605 + } | |
| 606 + | |
| 607 int ssl3_get_cert_verify(SSL *s) | |
| 608 { | |
| 609 EVP_PKEY *pkey=NULL; | |
| 610 diff --git a/ssl/ssl.h b/ssl/ssl.h | |
| 611 index 9ab9495..dc8dff8 100644 | |
| 612 --- a/ssl/ssl.h | |
| 613 +++ b/ssl/ssl.h | |
| 614 @@ -801,6 +801,23 @@ struct ssl_ctx_st | |
| 615 /* Callback for status request */ | |
| 616 int (*tlsext_status_cb)(SSL *ssl, void *arg); | |
| 617 void *tlsext_status_arg; | |
| 618 + | |
| 619 + /* Next protocol negotiation information */ | |
| 620 + /* (for experimental NPN extension). */ | |
| 621 + | |
| 622 + /* For a server, this contains a callback function by which the set of | |
| 623 + * advertised protocols can be provided. */ | |
| 624 + int (*next_protos_advertised_cb)(SSL *s, const unsigned char **buf, | |
| 625 + unsigned int *len, void *arg); | |
| 626 + void *next_protos_advertised_cb_arg; | |
| 627 + /* For a client, this contains a callback function that selects the | |
| 628 + * next protocol from the list provided by the server. */ | |
| 629 + int (*next_proto_select_cb)(SSL *s, unsigned char **out, | |
| 630 + unsigned char *outlen, | |
| 631 + const unsigned char *in, | |
| 632 + unsigned int inlen, | |
| 633 + void *arg); | |
| 634 + void *next_proto_select_cb_arg; | |
| 635 #endif | |
| 636 | |
| 637 }; | |
| 638 @@ -857,6 +874,15 @@ int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
; | |
| 639 #endif | |
| 640 void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL
*ssl, unsigned char *cookie, unsigned int *cookie_len)); | |
| 641 void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL
*ssl, unsigned char *cookie, unsigned int cookie_len)); | |
| 642 +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, int (*cb) (SSL *ssl, con
st unsigned char **out, unsigned int *outlen, void *arg), void *arg); | |
| 643 +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, int (*cb) (SSL *ssl, unsigned
char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen,
void *arg), void *arg); | |
| 644 + | |
| 645 +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const uns
igned char *in, unsigned int inlen, const unsigned char *client, unsigned int cl
ient_len); | |
| 646 +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, u
nsigned *len); | |
| 647 + | |
| 648 +#define OPENSSL_NPN_UNSUPPORTED 0 | |
| 649 +#define OPENSSL_NPN_NEGOTIATED 1 | |
| 650 +#define OPENSSL_NPN_NO_OVERLAP 2 | |
| 651 | |
| 652 #define SSL_NOTHING 1 | |
| 653 #define SSL_WRITING 2 | |
| 654 @@ -1054,6 +1080,16 @@ struct ssl_st | |
| 655 /* RFC4507 session ticket expected to be received or sent */ | |
| 656 int tlsext_ticket_expected; | |
| 657 SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ | |
| 658 + | |
| 659 + /* Next protocol negotiation. For the client, this is the protocol that | |
| 660 + * we sent in NextProtocol and is set when handling ServerHello | |
| 661 + * extensions. | |
| 662 + * | |
| 663 + * For a server, this is the client's selected_protocol from | |
| 664 + * NextProtocol and is set when handling the NextProtocol message, | |
| 665 + * before the Finished message. */ | |
| 666 + unsigned char *next_proto_negotiated; | |
| 667 + unsigned char next_proto_negotiated_len; | |
| 668 #define session_ctx initial_ctx | |
| 669 #else | |
| 670 #define session_ctx ctx | |
| 671 @@ -1761,6 +1797,7 @@ void ERR_load_SSL_strings(void); | |
| 672 #define SSL_F_SSL3_GET_KEY_EXCHANGE 141 | |
| 673 #define SSL_F_SSL3_GET_MESSAGE 142 | |
| 674 #define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283 | |
| 675 +#define SSL_F_SSL3_GET_NEXT_PROTO 297 | |
| 676 #define SSL_F_SSL3_GET_RECORD 143 | |
| 677 #define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144 | |
| 678 #define SSL_F_SSL3_GET_SERVER_DONE 145 | |
| 679 @@ -1827,6 +1864,7 @@ void ERR_load_SSL_strings(void); | |
| 680 #define SSL_F_SSL_INIT_WBIO_BUFFER 184 | |
| 681 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 | |
| 682 #define SSL_F_SSL_NEW 186 | |
| 683 +#define SSL_F_SSL_NEXT_PROTOS_PARSE 298 | |
| 684 #define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 287 | |
| 685 #define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 290 | |
| 686 #define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 289 | |
| 687 @@ -1869,6 +1907,7 @@ void ERR_load_SSL_strings(void); | |
| 688 #define SSL_F_TLS1_ENC 210 | |
| 689 #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 | |
| 690 #define SSL_F_WRITE_PENDING 212 | |
| 691 +/* Next entry: 299 */ | |
| 692 | |
| 693 /* Reason codes. */ | |
| 694 #define SSL_R_APP_DATA_IN_HANDSHAKE 100 | |
| 695 @@ -1939,6 +1978,8 @@ void ERR_load_SSL_strings(void); | |
| 696 #define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 | |
| 697 #define SSL_R_EXTRA_DATA_IN_MESSAGE 153 | |
| 698 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 | |
| 699 +#define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS 334 | |
| 700 +#define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION 335 | |
| 701 #define SSL_R_HTTPS_PROXY_REQUEST 155 | |
| 702 #define SSL_R_HTTP_REQUEST 156 | |
| 703 #define SSL_R_ILLEGAL_PADDING 283 | |
| 704 @@ -2120,6 +2161,7 @@ void ERR_load_SSL_strings(void); | |
| 705 #define SSL_R_WRONG_VERSION_NUMBER 267 | |
| 706 #define SSL_R_X509_LIB 268 | |
| 707 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 | |
| 708 +/* Next entry: 335 or 1115 */ | |
| 709 | |
| 710 #ifdef __cplusplus | |
| 711 } | |
| 712 diff --git a/ssl/ssl3.h b/ssl/ssl3.h | |
| 713 index afbdd70..54b73b7 100644 | |
| 714 --- a/ssl/ssl3.h | |
| 715 +++ b/ssl/ssl3.h | |
| 716 @@ -394,6 +394,9 @@ typedef struct ssl3_state_st | |
| 717 | |
| 718 int in_read_app_data; | |
| 719 | |
| 720 + /* Set if we saw the Next Protocol Negotiation extension from our peer.
*/ | |
| 721 + int next_proto_neg_seen; | |
| 722 + | |
| 723 struct { | |
| 724 /* actually only needs to be 16+20 */ | |
| 725 unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2]; | |
| 726 @@ -484,6 +487,8 @@ typedef struct ssl3_state_st | |
| 727 #define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT) | |
| 728 #define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT) | |
| 729 #define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT) | |
| 730 +#define SSL3_ST_CW_NEXT_PROTO_A (0x200|SSL_ST_CONNECT) | |
| 731 +#define SSL3_ST_CW_NEXT_PROTO_B (0x201|SSL_ST_CONNECT) | |
| 732 #define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT) | |
| 733 #define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT) | |
| 734 /* read from server */ | |
| 735 @@ -529,6 +534,8 @@ typedef struct ssl3_state_st | |
| 736 #define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT) | |
| 737 #define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT) | |
| 738 #define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT) | |
| 739 +#define SSL3_ST_SR_NEXT_PROTO_A (0x210|SSL_ST_ACCEPT) | |
| 740 +#define SSL3_ST_SR_NEXT_PROTO_B (0x211|SSL_ST_ACCEPT) | |
| 741 #define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT) | |
| 742 #define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT) | |
| 743 /* write to client */ | |
| 744 @@ -553,6 +560,7 @@ typedef struct ssl3_state_st | |
| 745 #define SSL3_MT_CLIENT_KEY_EXCHANGE 16 | |
| 746 #define SSL3_MT_FINISHED 20 | |
| 747 #define SSL3_MT_CERTIFICATE_STATUS 22 | |
| 748 +#define SSL3_MT_NEXT_PROTO 67 | |
| 749 #define DTLS1_MT_HELLO_VERIFY_REQUEST 3 | |
| 750 | |
| 751 | |
| 752 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c | |
| 753 index 7eb5202..ff9c856 100644 | |
| 754 --- a/ssl/ssl_err.c | |
| 755 +++ b/ssl/ssl_err.c | |
| 756 @@ -154,6 +154,7 @@ static ERR_STRING_DATA SSL_str_functs[]= | |
| 757 {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE), "SSL3_GET_KEY_EXCHANGE"}, | |
| 758 {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE), "SSL3_GET_MESSAGE"}, | |
| 759 {ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET), "SSL3_GET_NEW_SESSION_TICKET"}, | |
| 760 +{ERR_FUNC(SSL_F_SSL3_GET_NEXT_PROTO), "SSL3_GET_NEXT_PROTO"}, | |
| 761 {ERR_FUNC(SSL_F_SSL3_GET_RECORD), "SSL3_GET_RECORD"}, | |
| 762 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE), "SSL3_GET_SERVER_CERTIFICATE"}, | |
| 763 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE), "SSL3_GET_SERVER_DONE"}, | |
| 764 @@ -220,6 +221,7 @@ static ERR_STRING_DATA SSL_str_functs[]= | |
| 765 {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "SSL_INIT_WBIO_BUFFER"}, | |
| 766 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"}, | |
| 767 {ERR_FUNC(SSL_F_SSL_NEW), "SSL_new"}, | |
| 768 +{ERR_FUNC(SSL_F_SSL_NEXT_PROTOS_PARSE), "SSL_next_protos_parse"}, | |
| 769 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT), "SSL_PARSE_CLIEN
THELLO_RENEGOTIATE_EXT"}, | |
| 770 {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT), "SSL_PARSE_CLIENTHELLO_TLSEXT"}, | |
| 771 {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT), "SSL_PARSE_SERVE
RHELLO_RENEGOTIATE_EXT"}, | |
| 772 @@ -335,6 +337,8 @@ static ERR_STRING_DATA SSL_str_reasons[]= | |
| 773 {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE),"excessive message size"}, | |
| 774 {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) ,"extra data in message"}, | |
| 775 {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS),"got a fin before a ccs"}, | |
| 776 +{ERR_REASON(SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS),"got next proto before a ccs"}, | |
| 777 +{ERR_REASON(SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION),"got next proto without see
ing extension"}, | |
| 778 {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST) ,"https proxy request"}, | |
| 779 {ERR_REASON(SSL_R_HTTP_REQUEST) ,"http request"}, | |
| 780 {ERR_REASON(SSL_R_ILLEGAL_PADDING) ,"illegal padding"}, | |
| 781 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c | |
| 782 index 96e056d..cfa70ec 100644 | |
| 783 --- a/ssl/ssl_lib.c | |
| 784 +++ b/ssl/ssl_lib.c | |
| 785 @@ -323,6 +323,7 @@ SSL *SSL_new(SSL_CTX *ctx) | |
| 786 s->tlsext_ocsp_resplen = -1; | |
| 787 CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); | |
| 788 s->initial_ctx=ctx; | |
| 789 + s->next_proto_negotiated = NULL; | |
| 790 #endif | |
| 791 s->verify_result=X509_V_OK; | |
| 792 | |
| 793 @@ -532,6 +533,11 @@ void SSL_free(SSL *s) | |
| 794 kssl_ctx_free(s->kssl_ctx); | |
| 795 #endif /* OPENSSL_NO_KRB5 */ | |
| 796 | |
| 797 +#ifndef OPENSSL_NO_TLSEXT | |
| 798 + if (s->next_proto_negotiated) | |
| 799 + OPENSSL_free(s->next_proto_negotiated); | |
| 800 +#endif | |
| 801 + | |
| 802 OPENSSL_free(s); | |
| 803 } | |
| 804 | |
| 805 @@ -1576,6 +1582,8 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) | |
| 806 ret->tlsext_status_cb = 0; | |
| 807 ret->tlsext_status_arg = NULL; | |
| 808 | |
| 809 + ret->next_protos_advertised_cb = 0; | |
| 810 + ret->next_proto_select_cb = 0; | |
| 811 #endif | |
| 812 | |
| 813 #ifndef OPENSSL_NO_ENGINE | |
| 814 @@ -1677,6 +1685,7 @@ void SSL_CTX_free(SSL_CTX *a) | |
| 815 if (a->client_cert_engine) | |
| 816 ENGINE_finish(a->client_cert_engine); | |
| 817 #endif | |
| 818 + | |
| 819 OPENSSL_free(a); | |
| 820 } | |
| 821 | |
| 822 @@ -2752,6 +2761,123 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write
_p, int version, int con | |
| 823 SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); | |
| 824 } | |
| 825 | |
| 826 +#ifndef OPENSSL_NO_TLSEXT | |
| 827 +/* SSL_select_next_proto implements the standard protocol selection. It is | |
| 828 + * expected that this function is called from the callback set by | |
| 829 + * SSL_CTX_set_next_proto_select_cb. | |
| 830 + * | |
| 831 + * The protocol data is assumed to be a vector of 8-bit, length prefixed byte | |
| 832 + * strings. The length byte itself is not included in the length. A byte | |
| 833 + * string of length 0 is invalid. No byte string may be truncated. | |
| 834 + * | |
| 835 + * The current, but experimental algorithm for selecting the protocol is: | |
| 836 + * | |
| 837 + * 1) If the server doesn't support NPN then this is indicated to the | |
| 838 + * callback. In this case, the client application has to abort the connection | |
| 839 + * or have a default application level protocol. | |
| 840 + * | |
| 841 + * 2) If the server supports NPN, but advertises an empty list then the | |
| 842 + * client selects the first protcol in its list, but indicates via the | |
| 843 + * API that this fallback case was enacted. | |
| 844 + * | |
| 845 + * 3) Otherwise, the client finds the first protocol in the server's list | |
| 846 + * that it supports and selects this protocol. This is because it's | |
| 847 + * assumed that the server has better information about which protocol | |
| 848 + * a client should use. | |
| 849 + * | |
| 850 + * 4) If the client doesn't support any of the server's advertised | |
| 851 + * protocols, then this is treated the same as case 2. | |
| 852 + * | |
| 853 + * It returns either | |
| 854 + * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or | |
| 855 + * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. | |
| 856 + */ | |
| 857 +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const uns
igned char *server, unsigned int server_len, const unsigned char *client, unsign
ed int client_len) | |
| 858 + { | |
| 859 + unsigned int i, j; | |
| 860 + const unsigned char *result; | |
| 861 + int status = OPENSSL_NPN_UNSUPPORTED; | |
| 862 + | |
| 863 + /* For each protocol in server preference order, see if we support it. *
/ | |
| 864 + for (i = 0; i < server_len; ) | |
| 865 + { | |
| 866 + for (j = 0; j < client_len; ) | |
| 867 + { | |
| 868 + if (server[i] == client[j] && | |
| 869 + memcmp(&server[i+1], &client[j+1], server[i]) == 0) | |
| 870 + { | |
| 871 + /* We found a match */ | |
| 872 + result = &server[i]; | |
| 873 + status = OPENSSL_NPN_NEGOTIATED; | |
| 874 + goto found; | |
| 875 + } | |
| 876 + j += client[j]; | |
| 877 + j++; | |
| 878 + } | |
| 879 + i += server[i]; | |
| 880 + i++; | |
| 881 + } | |
| 882 + | |
| 883 + /* There's no overlap between our protocols and the server's list. */ | |
| 884 + result = client; | |
| 885 + status = OPENSSL_NPN_NO_OVERLAP; | |
| 886 + | |
| 887 + found: | |
| 888 + *out = (unsigned char *) result + 1; | |
| 889 + *outlen = result[0]; | |
| 890 + return status; | |
| 891 + } | |
| 892 + | |
| 893 +/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's | |
| 894 + * requested protocol for this connection and returns 0. If the client didn't | |
| 895 + * request any protocol, then *data is set to NULL. | |
| 896 + * | |
| 897 + * Note that the client can request any protocol it chooses. The value returned | |
| 898 + * from this function need not be a member of the list of supported protocols | |
| 899 + * provided by the callback. | |
| 900 + */ | |
| 901 +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, u
nsigned *len) | |
| 902 + { | |
| 903 + *data = s->next_proto_negotiated; | |
| 904 + if (!*data) { | |
| 905 + *len = 0; | |
| 906 + } else { | |
| 907 + *len = s->next_proto_negotiated_len; | |
| 908 + } | |
| 909 +} | |
| 910 + | |
| 911 +/* SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a | |
| 912 + * TLS server needs a list of supported protocols for Next Protocol | |
| 913 + * Negotiation. The returned list must be in wire format. The list is returned | |
| 914 + * by setting |out| to point to it and |outlen| to its length. This memory will | |
| 915 + * not be modified, but one should assume that the SSL* keeps a reference to | |
| 916 + * it. | |
| 917 + * | |
| 918 + * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. Othe
rwise, no | |
| 919 + * such extension will be included in the ServerHello. */ | |
| 920 +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, c
onst unsigned char **out, unsigned int *outlen, void *arg), void *arg) | |
| 921 + { | |
| 922 + ctx->next_protos_advertised_cb = cb; | |
| 923 + ctx->next_protos_advertised_cb_arg = arg; | |
| 924 + } | |
| 925 + | |
| 926 +/* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a | |
| 927 + * client needs to select a protocol from the server's provided list. |out| | |
| 928 + * must be set to point to the selected protocol (which may be within |in|). | |
| 929 + * The length of the protocol name must be written into |outlen|. The server's | |
| 930 + * advertised protocols are provided in |in| and |inlen|. The callback can | |
| 931 + * assume that |in| is syntactically valid. | |
| 932 + * | |
| 933 + * The client must select a protocol. It is fatal to the connection if this | |
| 934 + * callback returns a value other than SSL_TLSEXT_ERR_OK. | |
| 935 + */ | |
| 936 +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned
char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen,
void *arg), void *arg) | |
| 937 + { | |
| 938 + ctx->next_proto_select_cb = cb; | |
| 939 + ctx->next_proto_select_cb_arg = arg; | |
| 940 + } | |
| 941 +#endif | |
| 942 + | |
| 943 int SSL_cutthrough_complete(const SSL *s) | |
| 944 { | |
| 945 return (!s->server && /* cutthrough only applies to clie
nts */ | |
| 946 diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h | |
| 947 index e305db4..a9183ff 100644 | |
| 948 --- a/ssl/ssl_locl.h | |
| 949 +++ b/ssl/ssl_locl.h | |
| 950 @@ -895,6 +895,7 @@ int ssl3_get_server_certificate(SSL *s); | |
| 951 int ssl3_check_cert_and_algorithm(SSL *s); | |
| 952 #ifndef OPENSSL_NO_TLSEXT | |
| 953 int ssl3_check_finished(SSL *s); | |
| 954 +int ssl3_send_next_proto(SSL *s); | |
| 955 #endif | |
| 956 | |
| 957 int dtls1_client_hello(SSL *s); | |
| 958 @@ -913,6 +914,7 @@ int ssl3_check_client_hello(SSL *s); | |
| 959 int ssl3_get_client_certificate(SSL *s); | |
| 960 int ssl3_get_client_key_exchange(SSL *s); | |
| 961 int ssl3_get_cert_verify(SSL *s); | |
| 962 +int ssl3_get_next_proto(SSL *s); | |
| 963 | |
| 964 int dtls1_send_hello_request(SSL *s); | |
| 965 int dtls1_send_server_hello(SSL *s); | |
| 966 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c | |
| 967 index 8b53112..fd35b18 100644 | |
| 968 --- a/ssl/t1_lib.c | |
| 969 +++ b/ssl/t1_lib.c | |
| 970 @@ -271,6 +271,16 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned
char *p, unsigned cha | |
| 971 i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); | |
| 972 } | |
| 973 | |
| 974 + if (s->ctx->next_proto_select_cb) | |
| 975 + { | |
| 976 + /* The client advertises an emtpy extension to indicate its | |
| 977 + * support for Next Protocol Negotiation */ | |
| 978 + if (limit - ret - 4 < 0) | |
| 979 + return NULL; | |
| 980 + s2n(TLSEXT_TYPE_next_proto_neg,ret); | |
| 981 + s2n(0,ret); | |
| 982 + } | |
| 983 + | |
| 984 if ((extdatalen = ret-p-2)== 0) | |
| 985 return p; | |
| 986 | |
| 987 @@ -282,6 +292,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned c
har *p, unsigned cha | |
| 988 { | |
| 989 int extdatalen=0; | |
| 990 unsigned char *ret = p; | |
| 991 + char next_proto_neg_seen; | |
| 992 | |
| 993 /* don't add extensions for SSLv3, unless doing secure renegotiation */ | |
| 994 if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) | |
| 995 @@ -337,6 +348,26 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned
char *p, unsigned cha | |
| 996 s2n(0,ret); | |
| 997 } | |
| 998 | |
| 999 + next_proto_neg_seen = s->s3->next_proto_neg_seen; | |
| 1000 + s->s3->next_proto_neg_seen = 0; | |
| 1001 + if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) | |
| 1002 + { | |
| 1003 + const unsigned char *npa; | |
| 1004 + unsigned int npalen; | |
| 1005 + int r; | |
| 1006 + | |
| 1007 + r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen, s->ctx->
next_protos_advertised_cb_arg); | |
| 1008 + if (r == SSL_TLSEXT_ERR_OK) | |
| 1009 + { | |
| 1010 + if ((long)(limit - ret - 4 - npalen) < 0) return NULL; | |
| 1011 + s2n(TLSEXT_TYPE_next_proto_neg,ret); | |
| 1012 + s2n(npalen,ret); | |
| 1013 + memcpy(ret, npa, npalen); | |
| 1014 + ret += npalen; | |
| 1015 + s->s3->next_proto_neg_seen = 1; | |
| 1016 + } | |
| 1017 + } | |
| 1018 + | |
| 1019 if ((extdatalen = ret-p-2)== 0) | |
| 1020 return p; | |
| 1021 | |
| 1022 @@ -576,6 +607,25 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
unsigned char *d, in | |
| 1023 else | |
| 1024 s->tlsext_status_type = -1; | |
| 1025 } | |
| 1026 + else if (type == TLSEXT_TYPE_next_proto_neg) | |
| 1027 + { | |
| 1028 + /* We shouldn't accept this extension on a | |
| 1029 + * renegotiation, but we currently do. | |
| 1030 + * | |
| 1031 + * s->new_session will be set on renegotiation, but we | |
| 1032 + * probably shouldn't rely that it couldn't be set on | |
| 1033 + * the initial renegotation too in certain cases (when | |
| 1034 + * there's some other reason to disallow resuming an | |
| 1035 + * earlier session -- the current code won't be doing | |
| 1036 + * anything like that, but this might change). | |
| 1037 + | |
| 1038 + * A valid sign that there's been a previous handshake | |
| 1039 + * in this connection is if s->s3->tmp.finish_md_len > | |
| 1040 + * 0. (We are talking about a check that will happen | |
| 1041 + * in the Hello protocol round, well before a new | |
| 1042 + * Finished message could have been computed.) */ | |
| 1043 + s->s3->next_proto_neg_seen = 1; | |
| 1044 + } | |
| 1045 | |
| 1046 /* session ticket processed earlier */ | |
| 1047 | |
| 1048 @@ -599,6 +649,24 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
unsigned char *d, in | |
| 1049 return 1; | |
| 1050 } | |
| 1051 | |
| 1052 +/* ssl_next_proto_validate validates a Next Protocol Negotiation block. No | |
| 1053 + * elements of zero length are allowed and the set of elements must exactly fil
l | |
| 1054 + * the length of the block. */ | |
| 1055 +static char ssl_next_proto_validate(unsigned char *d, unsigned len) | |
| 1056 + { | |
| 1057 + unsigned int off = 0; | |
| 1058 + | |
| 1059 + while (off < len) | |
| 1060 + { | |
| 1061 + if (d[off] == 0) | |
| 1062 + return 0; | |
| 1063 + off += d[off]; | |
| 1064 + off++; | |
| 1065 + } | |
| 1066 + | |
| 1067 + return off == len; | |
| 1068 + } | |
| 1069 + | |
| 1070 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, i
nt n, int *al) | |
| 1071 { | |
| 1072 unsigned short type; | |
| 1073 @@ -658,6 +726,37 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p,
unsigned char *d, in | |
| 1074 /* Set flag to expect CertificateStatus message */ | |
| 1075 s->tlsext_status_expected = 1; | |
| 1076 } | |
| 1077 + else if (type == TLSEXT_TYPE_next_proto_neg) | |
| 1078 + { | |
| 1079 + unsigned char *selected; | |
| 1080 + unsigned char selected_len; | |
| 1081 + | |
| 1082 + /* We must have requested it. */ | |
| 1083 + if ((s->ctx->next_proto_select_cb == NULL)) | |
| 1084 + { | |
| 1085 + *al = TLS1_AD_UNSUPPORTED_EXTENSION; | |
| 1086 + return 0; | |
| 1087 + } | |
| 1088 + /* The data must be valid */ | |
| 1089 + if (!ssl_next_proto_validate(data, size)) | |
| 1090 + { | |
| 1091 + *al = TLS1_AD_DECODE_ERROR; | |
| 1092 + return 0; | |
| 1093 + } | |
| 1094 + if (s->ctx->next_proto_select_cb(s, &selected, &selected
_len, data, size, s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) | |
| 1095 + { | |
| 1096 + *al = TLS1_AD_INTERNAL_ERROR; | |
| 1097 + return 0; | |
| 1098 + } | |
| 1099 + s->next_proto_negotiated = OPENSSL_malloc(selected_len); | |
| 1100 + if (!s->next_proto_negotiated) | |
| 1101 + { | |
| 1102 + *al = TLS1_AD_INTERNAL_ERROR; | |
| 1103 + return 0; | |
| 1104 + } | |
| 1105 + memcpy(s->next_proto_negotiated, selected, selected_len)
; | |
| 1106 + s->next_proto_negotiated_len = selected_len; | |
| 1107 + } | |
| 1108 else if (type == TLSEXT_TYPE_renegotiate) | |
| 1109 { | |
| 1110 if(!ssl_parse_serverhello_renegotiate_ext(s, data, size,
al)) | |
| 1111 diff --git a/ssl/tls1.h b/ssl/tls1.h | |
| 1112 index afe4807..71d76de 100644 | |
| 1113 --- a/ssl/tls1.h | |
| 1114 +++ b/ssl/tls1.h | |
| 1115 @@ -118,6 +118,9 @@ extern "C" { | |
| 1116 /* Temporary extension type */ | |
| 1117 #define TLSEXT_TYPE_renegotiate 0xff01 | |
| 1118 | |
| 1119 +/* This is not an IANA defined extension number */ | |
| 1120 +#define TLSEXT_TYPE_next_proto_neg 13172 | |
| 1121 + | |
| 1122 /* NameType value from RFC 3546 */ | |
| 1123 #define TLSEXT_NAMETYPE_host_name 0 | |
| 1124 /* status request value from RFC 3546 */ | |
| OLD | NEW |