diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/Makefile | 101 | ||||
-rw-r--r-- | ssl/d1_both.c | 142 | ||||
-rw-r--r-- | ssl/d1_clnt.c | 918 | ||||
-rw-r--r-- | ssl/d1_enc.c | 251 | ||||
-rw-r--r-- | ssl/d1_lib.c | 92 | ||||
-rw-r--r-- | ssl/d1_meth.c | 18 | ||||
-rw-r--r-- | ssl/d1_pkt.c | 66 | ||||
-rw-r--r-- | ssl/d1_srtp.c | 3 | ||||
-rw-r--r-- | ssl/d1_srvr.c | 903 | ||||
-rw-r--r-- | ssl/dtls1.h | 6 | ||||
-rw-r--r-- | ssl/heartbeat_test.c | 38 | ||||
-rw-r--r-- | ssl/s23_clnt.c | 24 | ||||
-rw-r--r-- | ssl/s23_srvr.c | 5 | ||||
-rw-r--r-- | ssl/s2_clnt.c | 16 | ||||
-rw-r--r-- | ssl/s2_lib.c | 5 | ||||
-rw-r--r-- | ssl/s3_both.c | 119 | ||||
-rw-r--r-- | ssl/s3_cbc.c | 2 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 466 | ||||
-rw-r--r-- | ssl/s3_enc.c | 36 | ||||
-rw-r--r-- | ssl/s3_lib.c | 656 | ||||
-rw-r--r-- | ssl/s3_pkt.c | 198 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 455 | ||||
-rw-r--r-- | ssl/srtp.h | 1 | ||||
-rw-r--r-- | ssl/ssl.h | 422 | ||||
-rw-r--r-- | ssl/ssl3.h | 62 | ||||
-rw-r--r-- | ssl/ssl_algs.c | 4 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 544 | ||||
-rw-r--r-- | ssl/ssl_ciph.c | 181 | ||||
-rw-r--r-- | ssl/ssl_conf.c | 683 | ||||
-rw-r--r-- | ssl/ssl_err.c | 267 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 431 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 316 | ||||
-rw-r--r-- | ssl/ssl_rsa.c | 292 | ||||
-rw-r--r-- | ssl/ssl_sess.c | 35 | ||||
-rw-r--r-- | ssl/ssl_txt.c | 2 | ||||
-rw-r--r-- | ssl/ssltest.c | 566 | ||||
-rw-r--r-- | ssl/t1_clnt.c | 8 | ||||
-rw-r--r-- | ssl/t1_enc.c | 68 | ||||
-rw-r--r-- | ssl/t1_ext.c | 298 | ||||
-rw-r--r-- | ssl/t1_lib.c | 2223 | ||||
-rw-r--r-- | ssl/t1_meth.c | 9 | ||||
-rw-r--r-- | ssl/t1_srvr.c | 9 | ||||
-rw-r--r-- | ssl/t1_trce.c | 1266 | ||||
-rw-r--r-- | ssl/tls1.h | 41 |
44 files changed, 8606 insertions, 3642 deletions
diff --git a/ssl/Makefile b/ssl/Makefile index 29d9e4528fc5..42f1af5c8e93 100644 --- a/ssl/Makefile +++ b/ssl/Makefile @@ -24,24 +24,24 @@ LIBSRC= \ s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c s3_cbc.c \ s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ - t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ + t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c d1_srtp.c \ + d1_both.c d1_srtp.c \ ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ ssl_ciph.c ssl_stat.c ssl_rsa.c \ - ssl_asn1.c ssl_txt.c ssl_algs.c \ - bio_ssl.c ssl_err.c kssl.c tls_srp.c t1_reneg.c ssl_utst.c + ssl_asn1.c ssl_txt.c ssl_algs.c ssl_conf.c \ + bio_ssl.c ssl_err.c kssl.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.c LIBOBJ= \ s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o s3_cbc.o \ s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ - t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ + t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o d1_srtp.o\ + d1_both.o d1_srtp.o\ ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ ssl_ciph.o ssl_stat.o ssl_rsa.o \ - ssl_asn1.o ssl_txt.o ssl_algs.o \ - bio_ssl.o ssl_err.o kssl.o tls_srp.o t1_reneg.o ssl_utst.o + ssl_asn1.o ssl_txt.o ssl_algs.o ssl_conf.o \ + bio_ssl.o ssl_err.o kssl.o t1_reneg.o tls_srp.o t1_trce.o ssl_utst.o SRC= $(LIBSRC) @@ -166,27 +166,6 @@ d1_clnt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h d1_clnt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h d1_clnt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_clnt.c d1_clnt.o: kssl_lcl.h ssl_locl.h -d1_enc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -d1_enc.o: ../include/openssl/buffer.h ../include/openssl/comp.h -d1_enc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h -d1_enc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -d1_enc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -d1_enc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h -d1_enc.o: ../include/openssl/evp.h ../include/openssl/hmac.h -d1_enc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h -d1_enc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h -d1_enc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h -d1_enc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -d1_enc.o: ../include/openssl/pem.h ../include/openssl/pem2.h -d1_enc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h -d1_enc.o: ../include/openssl/rand.h ../include/openssl/rsa.h -d1_enc.o: ../include/openssl/safestack.h ../include/openssl/sha.h -d1_enc.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -d1_enc.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h -d1_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h -d1_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h -d1_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h d1_enc.c -d1_enc.o: ssl_locl.h d1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h d1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h d1_lib.o: ../include/openssl/crypto.h ../include/openssl/dsa.h @@ -612,8 +591,7 @@ s3_enc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h s3_enc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h s3_enc.o: ../include/openssl/tls1.h ../include/openssl/x509.h s3_enc.o: ../include/openssl/x509_vfy.h s3_enc.c ssl_locl.h -s3_lib.o: ../crypto/ec/ec_lcl.h ../e_os.h ../include/openssl/asn1.h -s3_lib.o: ../include/openssl/bio.h ../include/openssl/bn.h +s3_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h s3_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h s3_lib.o: ../include/openssl/crypto.h ../include/openssl/dh.h s3_lib.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h @@ -779,6 +757,27 @@ ssl_ciph.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h ssl_ciph.o: ../include/openssl/stack.h ../include/openssl/symhacks.h ssl_ciph.o: ../include/openssl/tls1.h ../include/openssl/x509.h ssl_ciph.o: ../include/openssl/x509_vfy.h ssl_ciph.c ssl_locl.h +ssl_conf.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +ssl_conf.o: ../include/openssl/buffer.h ../include/openssl/comp.h +ssl_conf.o: ../include/openssl/conf.h ../include/openssl/crypto.h +ssl_conf.o: ../include/openssl/dh.h ../include/openssl/dsa.h +ssl_conf.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +ssl_conf.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +ssl_conf.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +ssl_conf.o: ../include/openssl/evp.h ../include/openssl/hmac.h +ssl_conf.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +ssl_conf.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +ssl_conf.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +ssl_conf.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +ssl_conf.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +ssl_conf.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +ssl_conf.o: ../include/openssl/safestack.h ../include/openssl/sha.h +ssl_conf.o: ../include/openssl/srtp.h ../include/openssl/ssl.h +ssl_conf.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +ssl_conf.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +ssl_conf.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +ssl_conf.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_conf.c +ssl_conf.o: ssl_locl.h ssl_err.o: ../include/openssl/asn1.h ../include/openssl/bio.h ssl_err.o: ../include/openssl/buffer.h ../include/openssl/comp.h ssl_err.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h @@ -980,6 +979,26 @@ t1_enc.o: ../include/openssl/ssl3.h ../include/openssl/stack.h t1_enc.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h t1_enc.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h t1_enc.o: t1_enc.c +t1_ext.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_ext.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_ext.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_ext.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_ext.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_ext.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_ext.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_ext.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_ext.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_ext.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_ext.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_ext.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_ext.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +t1_ext.o: ../include/openssl/safestack.h ../include/openssl/sha.h +t1_ext.o: ../include/openssl/srtp.h ../include/openssl/ssl.h +t1_ext.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +t1_ext.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +t1_ext.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +t1_ext.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h +t1_ext.o: t1_ext.c t1_lib.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h t1_lib.o: ../include/openssl/buffer.h ../include/openssl/comp.h t1_lib.o: ../include/openssl/conf.h ../include/openssl/crypto.h @@ -1062,6 +1081,26 @@ t1_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c +t1_trce.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +t1_trce.o: ../include/openssl/buffer.h ../include/openssl/comp.h +t1_trce.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +t1_trce.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +t1_trce.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +t1_trce.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +t1_trce.o: ../include/openssl/evp.h ../include/openssl/hmac.h +t1_trce.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +t1_trce.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +t1_trce.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +t1_trce.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +t1_trce.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +t1_trce.o: ../include/openssl/pqueue.h ../include/openssl/rsa.h +t1_trce.o: ../include/openssl/safestack.h ../include/openssl/sha.h +t1_trce.o: ../include/openssl/srtp.h ../include/openssl/ssl.h +t1_trce.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h +t1_trce.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +t1_trce.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +t1_trce.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h +t1_trce.o: t1_trce.c tls_srp.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h tls_srp.o: ../include/openssl/bn.h ../include/openssl/buffer.h tls_srp.o: ../include/openssl/comp.h ../include/openssl/crypto.h diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 8dd8ea33ca79..b4ee7abe27dc 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -279,13 +279,17 @@ int dtls1_do_write(SSL *s, int type) (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); - if (s->write_hash) - mac_size = EVP_MD_CTX_size(s->write_hash); - else + if (s->write_hash) { + if (s->enc_write_ctx + && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE) + mac_size = 0; + else + mac_size = EVP_MD_CTX_size(s->write_hash); + } else mac_size = 0; if (s->enc_write_ctx && - (EVP_CIPHER_mode(s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) + (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE)) blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher); else blocksize = 0; @@ -978,59 +982,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) return (-1); } -int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) -{ - unsigned char *p, *d; - int i; - unsigned long l; - - if (s->state == a) { - d = (unsigned char *)s->init_buf->data; - p = &(d[DTLS1_HM_HEADER_LENGTH]); - - i = s->method->ssl3_enc->final_finish_mac(s, - sender, slen, - s->s3->tmp.finish_md); - s->s3->tmp.finish_md_len = i; - memcpy(p, s->s3->tmp.finish_md, i); - p += i; - l = i; - - /* - * Copy the finished so we can use it for renegotiation checks - */ - if (s->type == SSL_ST_CONNECT) { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i); - s->s3->previous_client_finished_len = i; - } else { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i); - s->s3->previous_server_finished_len = i; - } - -#ifdef OPENSSL_SYS_WIN16 - /* - * MSVC 1.5 does not clear the top bytes of the word unless I do - * this. - */ - l &= 0xffff; -#endif - - d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l); - s->init_num = (int)l + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state = b; - } - - /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} - /*- * for these 2 messages, we need to * ssl->enc_read_ctx re-init @@ -1071,77 +1022,6 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) return (dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); } -static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) -{ - int n; - unsigned char *p; - - n = i2d_X509(x, NULL); - if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) { - SSLerr(SSL_F_DTLS1_ADD_CERT_TO_BUF, ERR_R_BUF_LIB); - return 0; - } - p = (unsigned char *)&(buf->data[*l]); - l2n3(n, p); - i2d_X509(x, &p); - *l += n + 3; - - return 1; -} - -unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) -{ - unsigned char *p; - int i; - unsigned long l = 3 + DTLS1_HM_HEADER_LENGTH; - BUF_MEM *buf; - - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - buf = s->init_buf; - if (!BUF_MEM_grow_clean(buf, 10)) { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB); - return (0); - } - if (x != NULL) { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx, s->ctx->cert_store, x, NULL)) { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB); - return (0); - } - - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { - x = sk_X509_value(xs_ctx.chain, i); - - if (!dtls1_add_cert_to_buf(buf, &l, x)) { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - /* Thawte special :-) */ - for (i = 0; i < sk_X509_num(s->ctx->extra_certs); i++) { - x = sk_X509_value(s->ctx->extra_certs, i); - if (!dtls1_add_cert_to_buf(buf, &l, x)) - return 0; - } - - l -= (3 + DTLS1_HM_HEADER_LENGTH); - - p = (unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); - l2n3(l, p); - l += 3; - p = (unsigned char *)&(buf->data[0]); - p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); - - l += DTLS1_HM_HEADER_LENGTH; - return (l); -} - int dtls1_read_failed(SSL *s, int code) { if (code > 0) { @@ -1244,10 +1124,10 @@ int dtls1_buffer_message(SSL *s, int is_ccs) memcpy(frag->fragment, s->init_buf->data, s->init_num); if (is_ccs) { + /* For DTLS1_BAD_VER the header length is non-standard */ OPENSSL_assert(s->d1->w_msg_hdr.msg_len + - ((s->version == - DTLS1_VERSION) ? DTLS1_CCS_HEADER_LENGTH : 3) == - (unsigned int)s->init_num); + ((s->version==DTLS1_BAD_VER)?3:DTLS1_CCS_HEADER_LENGTH) + == (unsigned int)s->init_num); } else { OPENSSL_assert(s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num); diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c index 377c1e61f75c..4c2ccbf5ae08 100644 --- a/ssl/d1_clnt.c +++ b/ssl/d1_clnt.c @@ -135,13 +135,29 @@ static const SSL_METHOD *dtls1_get_client_method(int ver) { if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER) return (DTLSv1_client_method()); + else if (ver == DTLS1_2_VERSION) + return (DTLSv1_2_client_method()); else return (NULL); } -IMPLEMENT_dtls1_meth_func(DTLSv1_client_method, +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, + DTLSv1_client_method, ssl_undefined_function, - dtls1_connect, dtls1_get_client_method) + dtls1_connect, + dtls1_get_client_method, DTLSv1_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, + DTLSv1_2_client_method, + ssl_undefined_function, + dtls1_connect, + dtls1_get_client_method, DTLSv1_2_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, + DTLS_client_method, + ssl_undefined_function, + dtls1_connect, + dtls1_get_client_method, DTLSv1_2_enc_data) int dtls1_connect(SSL *s) { @@ -307,7 +323,7 @@ int dtls1_connect(SSL *s) ssl3_init_finished_mac(s); dtls1_start_timer(s); - ret = dtls1_client_hello(s); + ret = ssl3_client_hello(s); if (ret <= 0) goto end; @@ -462,7 +478,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: dtls1_start_timer(s); - ret = dtls1_send_client_certificate(s); + ret = ssl3_send_client_certificate(s); if (ret <= 0) goto end; s->state = SSL3_ST_CW_KEY_EXCH_A; @@ -472,7 +488,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: dtls1_start_timer(s); - ret = dtls1_send_client_key_exchange(s); + ret = ssl3_send_client_key_exchange(s); if (ret <= 0) goto end; @@ -517,7 +533,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: dtls1_start_timer(s); - ret = dtls1_send_client_verify(s); + ret = ssl3_send_client_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP @@ -583,13 +599,13 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_FINISHED_B: if (!s->hit) dtls1_start_timer(s); - ret = dtls1_send_finished(s, - SSL3_ST_CW_FINISHED_A, - SSL3_ST_CW_FINISHED_B, - s->method-> - ssl3_enc->client_finished_label, - s->method-> - ssl3_enc->client_finished_label_len); + ret = ssl3_send_finished(s, + SSL3_ST_CW_FINISHED_A, + SSL3_ST_CW_FINISHED_B, + s->method-> + ssl3_enc->client_finished_label, + s->method-> + ssl3_enc->client_finished_label_len); if (ret <= 0) goto end; s->state = SSL3_ST_CW_FLUSH; @@ -786,140 +802,18 @@ int dtls1_connect(SSL *s) return (ret); } -int dtls1_client_hello(SSL *s) -{ - unsigned char *buf; - unsigned char *p, *d; - unsigned int i, j; - unsigned long l; - SSL_COMP *comp; - - buf = (unsigned char *)s->init_buf->data; - if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { - SSL_SESSION *sess = s->session; - if ((s->session == NULL) || (s->session->ssl_version != s->version) || -#ifdef OPENSSL_NO_TLSEXT - !sess->session_id_length || -#else - (!sess->session_id_length && !sess->tlsext_tick) || -#endif - (s->session->not_resumable)) { - if (!ssl_get_new_session(s, 0)) - goto err; - } - /* else use the pre-loaded session */ - - p = s->s3->client_random; - - /* - * if client_random is initialized, reuse it, we are required to use - * same upon reply to HelloVerify - */ - for (i = 0; p[i] == '\0' && i < sizeof(s->s3->client_random); i++) ; - if (i == sizeof(s->s3->client_random)) - ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)); - - /* Do the message type and length last */ - d = p = &(buf[DTLS1_HM_HEADER_LENGTH]); - - *(p++) = s->version >> 8; - *(p++) = s->version & 0xff; - s->client_version = s->version; - - /* Random stuff */ - memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - - /* Session ID */ - if (s->new_session) - i = 0; - else - i = s->session->session_id_length; - *(p++) = i; - if (i != 0) { - if (i > sizeof s->session->session_id) { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } - memcpy(p, s->session->session_id, i); - p += i; - } - - /* cookie stuff */ - if (s->d1->cookie_len > sizeof(s->d1->cookie)) { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } - *(p++) = s->d1->cookie_len; - memcpy(p, s->d1->cookie, s->d1->cookie_len); - p += s->d1->cookie_len; - - /* Ciphers supported */ - i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0); - if (i == 0) { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE); - goto err; - } - s2n(i, p); - p += i; - - /* COMPRESSION */ - if (s->ctx->comp_methods == NULL) - j = 0; - else - j = sk_SSL_COMP_num(s->ctx->comp_methods); - *(p++) = 1 + j; - for (i = 0; i < j; i++) { - comp = sk_SSL_COMP_value(s->ctx->comp_methods, i); - *(p++) = comp->id; - } - *(p++) = 0; /* Add the NULL method */ - -#ifndef OPENSSL_NO_TLSEXT - /* TLS extensions */ - if (ssl_prepare_clienthello_tlsext(s) <= 0) { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } - if ((p = - ssl_add_clienthello_tlsext(s, p, - buf + SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } -#endif - - l = (p - d); - d = buf; - - d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l); - - s->state = SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num = p - buf; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_CW_CLNT_HELLO_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); - err: - return (-1); -} - static int dtls1_get_hello_verify(SSL *s) { int n, al, ok = 0; unsigned char *data; unsigned int cookie_len; + s->first_packet = 1; n = s->method->ssl_get_message(s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1, s->max_cert_list, &ok); + s->first_packet = 0; if (!ok) return ((int)n); @@ -931,13 +825,16 @@ static int dtls1_get_hello_verify(SSL *s) } data = (unsigned char *)s->init_msg; - - if ((data[0] != (s->version >> 8)) || (data[1] != (s->version & 0xff))) { +#if 0 + if (s->method->version != DTLS_ANY_VERSION && + ((data[0] != (s->version >> 8)) || (data[1] != (s->version & 0xff)))) + { SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY, SSL_R_WRONG_SSL_VERSION); s->version = (s->version & 0xff00) | data[1]; al = SSL_AD_PROTOCOL_VERSION; goto f_err; } +#endif data += 2; cookie_len = *(data++); @@ -957,746 +854,3 @@ static int dtls1_get_hello_verify(SSL *s) s->state = SSL_ST_ERR; return -1; } - -int dtls1_send_client_key_exchange(SSL *s) -{ - unsigned char *p, *d; - int n; - unsigned long alg_k; -#ifndef OPENSSL_NO_RSA - unsigned char *q; - EVP_PKEY *pkey = NULL; -#endif -#ifndef OPENSSL_NO_KRB5 - KSSL_ERR kssl_err; -#endif /* OPENSSL_NO_KRB5 */ -#ifndef OPENSSL_NO_ECDH - EC_KEY *clnt_ecdh = NULL; - const EC_POINT *srvr_ecpoint = NULL; - EVP_PKEY *srvr_pub_pkey = NULL; - unsigned char *encodedPoint = NULL; - int encoded_pt_len = 0; - BN_CTX *bn_ctx = NULL; -#endif - - if (s->state == SSL3_ST_CW_KEY_EXCH_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[DTLS1_HM_HEADER_LENGTH]); - - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - - /* Fool emacs indentation */ - if (0) { - } -#ifndef OPENSSL_NO_RSA - else if (alg_k & SSL_kRSA) { - RSA *rsa; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - - if (s->session->sess_cert == NULL) { - /* - * We should always have a server certificate with SSL_kRSA. - */ - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - if (s->session->sess_cert->peer_rsa_tmp != NULL) - rsa = s->session->sess_cert->peer_rsa_tmp; - else { - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC]. - x509); - if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) - || (pkey->pkey.rsa == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - rsa = pkey->pkey.rsa; - EVP_PKEY_free(pkey); - } - - tmp_buf[0] = s->client_version >> 8; - tmp_buf[1] = s->client_version & 0xff; - if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0) - goto err; - - s->session->master_key_length = sizeof tmp_buf; - - q = p; - /* Fix buf for TLS and [incidentally] DTLS */ - if (s->version > SSL3_VERSION) - p += 2; - n = RSA_public_encrypt(sizeof tmp_buf, - tmp_buf, p, rsa, RSA_PKCS1_PADDING); -# ifdef PKCS1_CHECK - if (s->options & SSL_OP_PKCS1_CHECK_1) - p[1]++; - if (s->options & SSL_OP_PKCS1_CHECK_2) - tmp_buf[0] = 0x70; -# endif - if (n <= 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_BAD_RSA_ENCRYPT); - goto err; - } - - /* Fix buf for TLS and [incidentally] DTLS */ - if (s->version > SSL3_VERSION) { - s2n(n, q); - n += 2; - } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); - } -#endif -#ifndef OPENSSL_NO_KRB5 - else if (alg_k & SSL_kKRB5) { - krb5_error_code krb5rc; - KSSL_CTX *kssl_ctx = s->kssl_ctx; - /* krb5_data krb5_ap_req; */ - krb5_data *enc_ticket; - krb5_data authenticator, *authp = NULL; - EVP_CIPHER_CTX ciph_ctx; - const EVP_CIPHER *enc = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH + EVP_MAX_IV_LENGTH]; - int padl, outl = sizeof(epms); - - EVP_CIPHER_CTX_init(&ciph_ctx); - -# ifdef KSSL_DEBUG - printf("ssl3_send_client_key_exchange(%lx & %lx)\n", - alg_k, SSL_kKRB5); -# endif /* KSSL_DEBUG */ - - authp = NULL; -# ifdef KRB5SENDAUTH - if (KRB5SENDAUTH) - authp = &authenticator; -# endif /* KRB5SENDAUTH */ - - krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, &kssl_err); - enc = kssl_map_enc(kssl_ctx->enctype); - if (enc == NULL) - goto err; -# ifdef KSSL_DEBUG - { - printf("kssl_cget_tkt rtn %d\n", krb5rc); - if (krb5rc && kssl_err.text) - printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); - } -# endif /* KSSL_DEBUG */ - - if (krb5rc) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason); - goto err; - } - - /*- - * 20010406 VRS - Earlier versions used KRB5 AP_REQ - ** in place of RFC 2712 KerberosWrapper, as in: - ** - ** Send ticket (copy to *p, set n = length) - ** n = krb5_ap_req.length; - ** memcpy(p, krb5_ap_req.data, krb5_ap_req.length); - ** if (krb5_ap_req.data) - ** kssl_krb5_free_data_contents(NULL,&krb5_ap_req); - ** - ** Now using real RFC 2712 KerberosWrapper - ** (Thanks to Simon Wilkinson <sxw@sxw.org.uk>) - ** Note: 2712 "opaque" types are here replaced - ** with a 2-byte length followed by the value. - ** Example: - ** KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms - ** Where "xx xx" = length bytes. Shown here with - ** optional authenticator omitted. - */ - - /* KerberosWrapper.Ticket */ - s2n(enc_ticket->length, p); - memcpy(p, enc_ticket->data, enc_ticket->length); - p += enc_ticket->length; - n = enc_ticket->length + 2; - - /* KerberosWrapper.Authenticator */ - if (authp && authp->length) { - s2n(authp->length, p); - memcpy(p, authp->data, authp->length); - p += authp->length; - n += authp->length + 2; - - free(authp->data); - authp->data = NULL; - authp->length = 0; - } else { - s2n(0, p); /* null authenticator length */ - n += 2; - } - - if (RAND_bytes(tmp_buf, sizeof tmp_buf) <= 0) - goto err; - - /*- - * 20010420 VRS. Tried it this way; failed. - * EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); - * EVP_CIPHER_CTX_set_key_length(&ciph_ctx, - * kssl_ctx->length); - * EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); - */ - - memset(iv, 0, sizeof iv); /* per RFC 1510 */ - EVP_EncryptInit_ex(&ciph_ctx, enc, NULL, kssl_ctx->key, iv); - EVP_EncryptUpdate(&ciph_ctx, epms, &outl, tmp_buf, - sizeof tmp_buf); - EVP_EncryptFinal_ex(&ciph_ctx, &(epms[outl]), &padl); - outl += padl; - if (outl > (int)sizeof epms) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); - - /* KerberosWrapper.EncryptedPreMasterSecret */ - s2n(outl, p); - memcpy(p, epms, outl); - p += outl; - n += outl + 2; - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); - OPENSSL_cleanse(epms, outl); - } -#endif -#ifndef OPENSSL_NO_DH - else if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) { - DH *dh_srvr, *dh_clnt; - - if (s->session->sess_cert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - - if (s->session->sess_cert->peer_dh_tmp != NULL) - dh_srvr = s->session->sess_cert->peer_dh_tmp; - else { - /* we get them from the cert */ - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); - goto err; - } - - /* generate a new random key */ - if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - if (!DH_generate_key(dh_clnt)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - - /* - * use the 'p' output buffer for the DH key, but make sure to - * clear it out afterwards - */ - - n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); - - if (n <= 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - /* clean up */ - memset(p, 0, n); - - /* send off the data */ - n = BN_num_bytes(dh_clnt->pub_key); - s2n(n, p); - BN_bn2bin(dh_clnt->pub_key, p); - n += 2; - - DH_free(dh_clnt); - - /* perhaps clean things up a bit EAY EAY EAY EAY */ - } -#endif -#ifndef OPENSSL_NO_ECDH - else if (alg_k & (SSL_kEECDH | SSL_kECDHr | SSL_kECDHe)) { - const EC_GROUP *srvr_group = NULL; - EC_KEY *tkey; - int ecdh_clnt_cert = 0; - int field_size = 0; - - if (s->session->sess_cert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - - /* - * Did we send out the client's ECDH share for use in premaster - * computation as part of client certificate? If so, set - * ecdh_clnt_cert to 1. - */ - if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) { - /* - * XXX: For now, we do not support client authentication - * using ECDH certificates. To add such support, one needs to - * add code that checks for appropriate conditions and sets - * ecdh_clnt_cert to 1. For example, the cert have an ECC key - * on the same curve as the server's and the key should be - * authorized for key agreement. One also needs to add code - * in ssl3_connect to skip sending the certificate verify - * message. if ((s->cert->key->privatekey != NULL) && - * (s->cert->key->privatekey->type == EVP_PKEY_EC) && ...) - * ecdh_clnt_cert = 1; - */ - } - - if (s->session->sess_cert->peer_ecdh_tmp != NULL) { - tkey = s->session->sess_cert->peer_ecdh_tmp; - } else { - /* Get the Server Public Key from Cert */ - srvr_pub_pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); - if ((srvr_pub_pkey == NULL) - || (srvr_pub_pkey->type != EVP_PKEY_EC) - || (srvr_pub_pkey->pkey.ec == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - tkey = srvr_pub_pkey->pkey.ec; - } - - srvr_group = EC_KEY_get0_group(tkey); - srvr_ecpoint = EC_KEY_get0_public_key(tkey); - - if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((clnt_ecdh = EC_KEY_new()) == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); - goto err; - } - if (ecdh_clnt_cert) { - /* - * Reuse key info from our certificate We only need our - * private key to perform the ECDH computation. - */ - const BIGNUM *priv_key; - tkey = s->cert->key->privatekey->pkey.ec; - priv_key = EC_KEY_get0_private_key(tkey); - if (priv_key == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } - if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_EC_LIB); - goto err; - } - } else { - /* Generate a new ECDH key pair */ - if (!(EC_KEY_generate_key(clnt_ecdh))) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_ECDH_LIB); - goto err; - } - } - - /* - * use the 'p' output buffer for the ECDH key, but make sure to - * clear it out afterwards - */ - - field_size = EC_GROUP_get_degree(srvr_group); - if (field_size <= 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - n = ECDH_compute_key(p, (field_size + 7) / 8, srvr_ecpoint, - clnt_ecdh, NULL); - if (n <= 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - - memset(p, 0, n); /* clean up */ - - if (ecdh_clnt_cert) { - /* Send empty client key exch message */ - n = 0; - } else { - /* - * First check the size of encoding and allocate memory - * accordingly. - */ - encoded_pt_len = - EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encoded_pt_len * sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Encode the public key */ - n = EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encoded_pt_len, bn_ctx); - - *p = n; /* length of encoded point */ - /* Encoded point will be copied here */ - p += 1; - /* copy the point */ - memcpy((unsigned char *)p, encodedPoint, n); - /* increment n to account for length field */ - n += 1; - } - - /* Free allocated memory */ - BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) - OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); - EVP_PKEY_free(srvr_pub_pkey); - } -#endif /* !OPENSSL_NO_ECDH */ - -#ifndef OPENSSL_NO_PSK - else if (alg_k & SSL_kPSK) { - char identity[PSK_MAX_IDENTITY_LEN]; - unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4]; - unsigned int pre_ms_len = 0, psk_len = 0; - int psk_err = 1; - - n = 0; - if (s->psk_client_callback == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_NO_CLIENT_CB); - goto err; - } - - psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, - identity, PSK_MAX_IDENTITY_LEN, - psk_or_pre_ms, - sizeof(psk_or_pre_ms)); - if (psk_len > PSK_MAX_PSK_LEN) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto psk_err; - } else if (psk_len == 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_IDENTITY_NOT_FOUND); - goto psk_err; - } - - /* create PSK pre_master_secret */ - pre_ms_len = 2 + psk_len + 2 + psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms + psk_len + 4, psk_or_pre_ms, psk_len); - s2n(psk_len, t); - memset(t, 0, psk_len); - t += psk_len; - s2n(psk_len, t); - - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = - BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL - && s->session->psk_identity_hint == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - if (s->session->psk_identity != NULL) - OPENSSL_free(s->session->psk_identity); - s->session->psk_identity = BUF_strdup(identity); - if (s->session->psk_identity == NULL) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - psk_or_pre_ms, - pre_ms_len); - n = strlen(identity); - s2n(n, p); - memcpy(p, identity, n); - n += 2; - psk_err = 0; - psk_err: - OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_err != 0) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; - } - } -#endif - else { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_CLIENT_KEY_EXCHANGE, n, 0, n); - /*- - *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n,d); - l2n(s->d1->handshake_write_seq,d); - s->d1->handshake_write_seq++; - */ - - s->state = SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num = n + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_CW_KEY_EXCH_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); - err: -#ifndef OPENSSL_NO_ECDH - BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) - OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); - EVP_PKEY_free(srvr_pub_pkey); -#endif - return (-1); -} - -int dtls1_send_client_verify(SSL *s) -{ - unsigned char *p, *d; - unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; - EVP_PKEY *pkey; -#ifndef OPENSSL_NO_RSA - unsigned u = 0; -#endif - unsigned long n; -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) - int j; -#endif - - if (s->state == SSL3_ST_CW_CERT_VRFY_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[DTLS1_HM_HEADER_LENGTH]); - pkey = s->cert->key->privatekey; - - s->method->ssl3_enc->cert_verify_mac(s, - NID_sha1, - &(data[MD5_DIGEST_LENGTH])); - -#ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) { - s->method->ssl3_enc->cert_verify_mac(s, NID_md5, &(data[0])); - if (RSA_sign(NID_md5_sha1, data, - MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, - &(p[2]), &u, pkey->pkey.rsa) <= 0) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, ERR_R_RSA_LIB); - goto err; - } - s2n(u, p); - n = u + 2; - } else -#endif -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) { - if (!DSA_sign(pkey->save_type, - &(data[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH, &(p[2]), - (unsigned int *)&j, pkey->pkey.dsa)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, ERR_R_DSA_LIB); - goto err; - } - s2n(j, p); - n = j + 2; - } else -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) { - if (!ECDSA_sign(pkey->save_type, - &(data[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH, &(p[2]), - (unsigned int *)&j, pkey->pkey.ec)) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, ERR_R_ECDSA_LIB); - goto err; - } - s2n(j, p); - n = j + 2; - } else -#endif - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); - goto err; - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_CERTIFICATE_VERIFY, n, 0, n); - - s->init_num = (int)n + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state = SSL3_ST_CW_CERT_VRFY_B; - } - - /* s->state = SSL3_ST_CW_CERT_VRFY_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); - err: - return (-1); -} - -int dtls1_send_client_certificate(SSL *s) -{ - X509 *x509 = NULL; - EVP_PKEY *pkey = NULL; - int i; - unsigned long l; - - if (s->state == SSL3_ST_CW_CERT_A) { - if ((s->cert == NULL) || - (s->cert->key->x509 == NULL) || - (s->cert->key->privatekey == NULL)) - s->state = SSL3_ST_CW_CERT_B; - else - s->state = SSL3_ST_CW_CERT_C; - } - - /* We need to get a client cert */ - if (s->state == SSL3_ST_CW_CERT_B) { - /* - * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP; - * return(-1); We then get retied later - */ - i = 0; - i = ssl_do_client_cert_cb(s, &x509, &pkey); - if (i < 0) { - s->rwstate = SSL_X509_LOOKUP; - return (-1); - } - s->rwstate = SSL_NOTHING; - if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { - s->state = SSL3_ST_CW_CERT_B; - if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) - i = 0; - } else if (i == 1) { - i = 0; - SSLerr(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE, - SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); - } - - if (x509 != NULL) - X509_free(x509); - if (pkey != NULL) - EVP_PKEY_free(pkey); - if (i == 0) { - if (s->version == SSL3_VERSION) { - s->s3->tmp.cert_req = 0; - ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE); - return (1); - } else { - s->s3->tmp.cert_req = 2; - } - } - - /* Ok, we have a cert */ - s->state = SSL3_ST_CW_CERT_C; - } - - if (s->state == SSL3_ST_CW_CERT_C) { - s->state = SSL3_ST_CW_CERT_D; - l = dtls1_output_cert_chain(s, - (s->s3->tmp.cert_req == - 2) ? NULL : s->cert->key->x509); - if (!l) { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - return 0; - } - s->init_num = (int)l; - s->init_off = 0; - - /* set header called by dtls1_output_cert_chain() */ - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - /* SSL3_ST_CW_CERT_D */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c deleted file mode 100644 index e876364f2c89..000000000000 --- a/ssl/d1_enc.c +++ /dev/null @@ -1,251 +0,0 @@ -/* ssl/d1_enc.c */ -/* - * DTLS implementation written by Nagendra Modadugu - * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. - */ -/* ==================================================================== - * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -#include <stdio.h> -#include "ssl_locl.h" -#ifndef OPENSSL_NO_COMP -# include <openssl/comp.h> -#endif -#include <openssl/evp.h> -#include <openssl/hmac.h> -#include <openssl/md5.h> -#include <openssl/rand.h> -#ifdef KSSL_DEBUG -# include <openssl/des.h> -#endif - -/*- - * dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. - * - * Returns: - * 0: (in non-constant time) if the record is publically invalid (i.e. too - * short etc). - * 1: if the record's padding is valid / the encryption was successful. - * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, - * an internal error occured. - */ -int dtls1_enc(SSL *s, int send) -{ - SSL3_RECORD *rec; - EVP_CIPHER_CTX *ds; - unsigned long l; - int bs, i, j, k, mac_size = 0; - const EVP_CIPHER *enc; - - if (send) { - if (EVP_MD_CTX_md(s->write_hash)) { - mac_size = EVP_MD_CTX_size(s->write_hash); - if (mac_size < 0) - return -1; - } - ds = s->enc_write_ctx; - rec = &(s->s3->wrec); - if (s->enc_write_ctx == NULL) - enc = NULL; - else { - enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); - if (rec->data != rec->input) - /* we can't write into the input stream */ - fprintf(stderr, "%s:%d: rec->data != rec->input\n", - __FILE__, __LINE__); - else if (EVP_CIPHER_block_size(ds->cipher) > 1) { - if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) - <= 0) - return -1; - } - } - } else { - if (EVP_MD_CTX_md(s->read_hash)) { - mac_size = EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(mac_size >= 0); - } - ds = s->enc_read_ctx; - rec = &(s->s3->rrec); - if (s->enc_read_ctx == NULL) - enc = NULL; - else - enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); - } - -#ifdef KSSL_DEBUG - printf("dtls1_enc(%d)\n", send); -#endif /* KSSL_DEBUG */ - - if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { - memmove(rec->data, rec->input, rec->length); - rec->input = rec->data; - } else { - l = rec->length; - bs = EVP_CIPHER_block_size(ds->cipher); - - if ((bs != 1) && send) { - i = bs - ((int)l % bs); - - /* Add weird padding of upto 256 bytes */ - - /* we need to add 'i' padding bytes of value j */ - j = i - 1; - if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) { - if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) - j++; - } - for (k = (int)l; k < (int)(l + i); k++) - rec->input[k] = j; - l += i; - rec->length += i; - } -#ifdef KSSL_DEBUG - { - unsigned long ui; - printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", - ds, rec->data, rec->input, l); - printf - ("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", - ds->buf_len, ds->cipher->key_len, DES_KEY_SZ, - DES_SCHEDULE_SZ, ds->cipher->iv_len); - printf("\t\tIV: "); - for (i = 0; i < ds->cipher->iv_len; i++) - printf("%02X", ds->iv[i]); - printf("\n"); - printf("\trec->input="); - for (ui = 0; ui < l; ui++) - printf(" %02x", rec->input[ui]); - printf("\n"); - } -#endif /* KSSL_DEBUG */ - - if (!send) { - if (l == 0 || l % bs != 0) - return 0; - } - - if (EVP_Cipher(ds, rec->data, rec->input, l) < 1) - return -1; - -#ifdef KSSL_DEBUG - { - unsigned long i; - printf("\trec->data="); - for (i = 0; i < l; i++) - printf(" %02x", rec->data[i]); - printf("\n"); - } -#endif /* KSSL_DEBUG */ - - if ((bs != 1) && !send) - return tls1_cbc_remove_padding(s, rec, bs, mac_size); - } - return (1); -} diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 011d7b7cbe69..ee78921ba8b0 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -62,16 +62,18 @@ #include <openssl/objects.h> #include "ssl_locl.h" -#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) +#if defined(OPENSSL_SYS_VMS) # include <sys/timeb.h> #endif static void get_current_time(struct timeval *t); +static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len); +static int dtls1_handshake_write(SSL *s); const char dtls1_version_str[] = "DTLSv1" OPENSSL_VERSION_PTEXT; int dtls1_listen(SSL *s, struct sockaddr *client); SSL3_ENC_METHOD DTLSv1_enc_data = { - dtls1_enc, + tls1_enc, tls1_mac, tls1_setup_key_block, tls1_generate_master_secret, @@ -83,6 +85,30 @@ SSL3_ENC_METHOD DTLSv1_enc_data = { TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, + SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV, + DTLS1_HM_HEADER_LENGTH, + dtls1_set_handshake_header, + dtls1_handshake_write +}; + +SSL3_ENC_METHOD DTLSv1_2_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_DTLS | SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS + | SSL_ENC_FLAG_SHA256_PRF | SSL_ENC_FLAG_TLS1_2_CIPHERS, + DTLS1_HM_HEADER_LENGTH, + dtls1_set_handshake_header, + dtls1_handshake_write }; long dtls1_default_timeout(void) @@ -244,9 +270,11 @@ void dtls1_clear(SSL *s) ssl3_clear(s); if (s->options & SSL_OP_CISCO_ANYCONNECT) - s->version = DTLS1_BAD_VER; + s->client_version = s->version = DTLS1_BAD_VER; + else if (s->method->version == DTLS_ANY_VERSION) + s->version = DTLS1_2_VERSION; else - s->version = DTLS1_VERSION; + s->version = s->method->version; } long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) @@ -271,14 +299,22 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) * highest enabled version (according to s->ctx->method, as version * negotiation may have changed s->method). */ -#if DTLS_MAX_VERSION != DTLS1_VERSION -# error Code needs update for DTLS_method() support beyond DTLS1_VERSION. -#endif + if (s->version == s->ctx->method->version) + return 1; /* - * Just one protocol version is supported so far; fail closed if the - * version is not as expected. + * Apparently we're using a version-flexible SSL_METHOD (not at its + * highest protocol version). */ - return s->version == DTLS_MAX_VERSION; + if (s->ctx->method->version == DTLS_method()->version) { +#if DTLS_MAX_VERSION != DTLS1_2_VERSION +# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION. +#endif + if (!(s->options & SSL_OP_NO_DTLSv1_2)) + return s->version == DTLS1_2_VERSION; + if (!(s->options & SSL_OP_NO_DTLSv1)) + return s->version == DTLS1_VERSION; + } + return 0; /* Unexpected state; fail closed. */ case DTLS_CTRL_SET_LINK_MTU: if (larg < (long)dtls1_link_min_mtu()) return 0; @@ -477,11 +513,22 @@ int dtls1_handle_timeout(SSL *s) static void get_current_time(struct timeval *t) { -#ifdef OPENSSL_SYS_WIN32 - struct _timeb tb; - _ftime(&tb); - t->tv_sec = (long)tb.time; - t->tv_usec = (long)tb.millitm * 1000; +#if defined(_WIN32) + SYSTEMTIME st; + union { + unsigned __int64 ul; + FILETIME ft; + } now; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &now.ft); +# ifdef __MINGW32__ + now.ul -= 116444736000000000ULL; +# else + now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ +# endif + t->tv_sec = (long)(now.ul / 10000000); + t->tv_usec = ((int)(now.ul % 10000000)) / 10; #elif defined(OPENSSL_SYS_VMS) struct timeb tb; ftime(&tb); @@ -509,3 +556,18 @@ int dtls1_listen(SSL *s, struct sockaddr *client) (void)BIO_dgram_get_peer(SSL_get_rbio(s), client); return 1; } + +static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) +{ + unsigned char *p = (unsigned char *)s->init_buf->data; + dtls1_set_message_header(s, p, htype, len, 0, len); + s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; + s->init_off = 0; + /* Buffer the message to handle re-xmits */ + dtls1_buffer_message(s, 0); +} + +static int dtls1_handshake_write(SSL *s) +{ + return dtls1_do_write(s, SSL3_RT_HANDSHAKE); +} diff --git a/ssl/d1_meth.c b/ssl/d1_meth.c index aaa718c92718..734077493f84 100644 --- a/ssl/d1_meth.c +++ b/ssl/d1_meth.c @@ -66,9 +66,23 @@ static const SSL_METHOD *dtls1_get_method(int ver) { if (ver == DTLS1_VERSION) return (DTLSv1_method()); + else if (ver == DTLS1_2_VERSION) + return (DTLSv1_2_method()); else return (NULL); } -IMPLEMENT_dtls1_meth_func(DTLSv1_method, - dtls1_accept, dtls1_connect, dtls1_get_method) +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, + DTLSv1_method, + dtls1_accept, + dtls1_connect, dtls1_get_method, DTLSv1_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, + DTLSv1_2_method, + dtls1_accept, + dtls1_connect, dtls1_get_method, DTLSv1_2_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, + DTLS_method, + dtls1_accept, + dtls1_connect, dtls1_get_method, DTLSv1_2_enc_data) diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index d659ed428e6d..fe30ec7d0042 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -612,6 +612,10 @@ int dtls1_get_record(SSL *s) p = s->packet; + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH, + s, s->msg_callback_arg); + /* Pull apart the header into the DTLS1_RECORD */ rr->type = *(p++); ssl_major = *(p++); @@ -1488,10 +1492,10 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned char *p, *pseq; int i, mac_size, clear = 0; int prefix_len = 0; + int eivlen; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; - int bs; /* * first check if there is a SSL3_BUFFER still being written out. This @@ -1570,27 +1574,41 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, *(p++) = type & 0xff; wr->type = type; - - *(p++) = (s->version >> 8); - *(p++) = s->version & 0xff; + /* + * Special case: for hello verify request, client version 1.0 and we + * haven't decided which version to use yet send back using version 1.0 + * header: otherwise some clients will ignore it. + */ + if (s->method->version == DTLS_ANY_VERSION) { + *(p++) = DTLS1_VERSION >> 8; + *(p++) = DTLS1_VERSION & 0xff; + } else { + *(p++) = s->version >> 8; + *(p++) = s->version & 0xff; + } /* field where we are to write out packet epoch, seq num and len */ pseq = p; p += 10; - /* lets setup the record stuff. */ - - /* - * Make space for the explicit IV in case of CBC. (this is a bit of a - * boundary violation, but what the heck). - */ - if (s->enc_write_ctx && - (EVP_CIPHER_mode(s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) - bs = EVP_CIPHER_block_size(s->enc_write_ctx->cipher); - else - bs = 0; + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } + /* Need explicit part of IV for GCM mode */ + else if (mode == EVP_CIPH_GCM_MODE) + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + else + eivlen = 0; + } else + eivlen = 0; - wr->data = p + bs; /* make room for IV in case of CBC */ + /* lets setup the record stuff. */ + wr->data = p + eivlen; /* make room for IV in case of CBC */ wr->length = (int)len; wr->input = (unsigned char *)buf; @@ -1616,7 +1634,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, */ if (mac_size != 0) { - if (s->method->ssl3_enc->mac(s, &(p[wr->length + bs]), 1) < 0) + if (s->method->ssl3_enc->mac(s, &(p[wr->length + eivlen]), 1) < 0) goto err; wr->length += mac_size; } @@ -1625,14 +1643,8 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, wr->input = p; wr->data = p; - /* ssl3_enc can only have an error on read */ - if (bs) { /* bs != 0 in case of CBC */ - RAND_pseudo_bytes(p, bs); - /* - * master IV and last CBC residue stand for the rest of randomness - */ - wr->length += bs; - } + if (eivlen) + wr->length += eivlen; if (s->method->ssl3_enc->enc(s, 1) < 1) goto err; @@ -1656,6 +1668,10 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, pseq += 6; s2n(wr->length, pseq); + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, pseq - DTLS1_RT_HEADER_LENGTH, + DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); + /* * we should now have wr->data pointing to the encrypted data, which is * wr->length long diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c index 6c6e07ce902b..64d0634a381e 100644 --- a/ssl/d1_srtp.c +++ b/ssl/d1_srtp.c @@ -117,11 +117,10 @@ #include <stdio.h> #include <openssl/objects.h> #include "ssl_locl.h" +#include "srtp.h" #ifndef OPENSSL_NO_SRTP -# include "srtp.h" - static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = { { "SRTP_AES128_CM_SHA1_80", diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 41c7dc519f1b..655333a25210 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -133,13 +133,29 @@ static const SSL_METHOD *dtls1_get_server_method(int ver) { if (ver == DTLS1_VERSION) return (DTLSv1_server_method()); + else if (ver == DTLS1_2_VERSION) + return (DTLSv1_2_server_method()); else return (NULL); } -IMPLEMENT_dtls1_meth_func(DTLSv1_server_method, +IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, + DTLSv1_server_method, dtls1_accept, - ssl_undefined_function, dtls1_get_server_method) + ssl_undefined_function, + dtls1_get_server_method, DTLSv1_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, + DTLSv1_2_server_method, + dtls1_accept, + ssl_undefined_function, + dtls1_get_server_method, DTLSv1_2_enc_data) + + IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, + DTLS_server_method, + dtls1_accept, + ssl_undefined_function, + dtls1_get_server_method, DTLSv1_2_enc_data) int dtls1_accept(SSL *s) { @@ -284,7 +300,7 @@ int dtls1_accept(SSL *s) s->shutdown = 0; dtls1_clear_record_buffer(s); dtls1_start_timer(s); - ret = dtls1_send_hello_request(s); + ret = ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A; @@ -392,7 +408,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); - ret = dtls1_send_server_hello(s); + ret = ssl3_send_server_hello(s); if (ret <= 0) goto end; @@ -431,7 +447,7 @@ int dtls1_accept(SSL *s) if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); - ret = dtls1_send_server_certificate(s); + ret = ssl3_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT @@ -474,7 +490,7 @@ int dtls1_accept(SSL *s) #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif - || (alg_k & SSL_kEDH) + || (alg_k & SSL_kDHE) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL @@ -487,7 +503,7 @@ int dtls1_accept(SSL *s) ) ) { dtls1_start_timer(s); - ret = dtls1_send_server_key_exchange(s); + ret = ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else @@ -541,7 +557,7 @@ int dtls1_accept(SSL *s) } else { s->s3->tmp.cert_request = 1; dtls1_start_timer(s); - ret = dtls1_send_certificate_request(s); + ret = ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG @@ -569,7 +585,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); - ret = dtls1_send_server_done(s); + ret = ssl3_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; @@ -597,22 +613,13 @@ int dtls1_accept(SSL *s) case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - /* Check for second client hello (MS SGC) */ - ret = ssl3_check_client_hello(s); - if (ret <= 0) - goto end; - if (ret == 2) { - dtls1_stop_timer(s); - s->state = SSL3_ST_SR_CLNT_HELLO_C; - } else { - if (s->s3->tmp.cert_request) { - ret = ssl3_get_client_certificate(s); - if (ret <= 0) - goto end; - } - s->init_num = 0; - s->state = SSL3_ST_SR_KEY_EXCH_A; + if (s->s3->tmp.cert_request) { + ret = ssl3_get_client_certificate(s); + if (ret <= 0) + goto end; } + s->init_num = 0; + s->state = SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: @@ -647,6 +654,25 @@ int dtls1_accept(SSL *s) */ s->state = SSL3_ST_SR_FINISHED_A; s->init_num = 0; + } else if (SSL_USE_SIGALGS(s)) { + s->state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + if (!s->session->peer) + break; + /* + * For sigalgs freeze the handshake buffer at this point and + * digest cached records. + */ + if (!s->s3->handshake_buffer) { + SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; + return -1; + } + s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; + if (!ssl3_digest_cached_records(s)) { + s->state = SSL_ST_ERR; + return -1; + } } else { s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; @@ -714,7 +740,7 @@ int dtls1_accept(SSL *s) #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: - ret = dtls1_send_newsession_ticket(s); + ret = ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state = SSL3_ST_SW_CHANGE_A; @@ -776,13 +802,13 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: - ret = dtls1_send_finished(s, - SSL3_ST_SW_FINISHED_A, - SSL3_ST_SW_FINISHED_B, - s->method-> - ssl3_enc->server_finished_label, - s->method-> - ssl3_enc->server_finished_label_len); + ret = ssl3_send_finished(s, + SSL3_ST_SW_FINISHED_A, + SSL3_ST_SW_FINISHED_B, + s->method-> + ssl3_enc->server_finished_label, + s->method-> + ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state = SSL3_ST_SW_FLUSH; @@ -889,29 +915,6 @@ int dtls1_accept(SSL *s) return (ret); } -int dtls1_send_hello_request(SSL *s) -{ - unsigned char *p; - - if (s->state == SSL3_ST_SW_HELLO_REQ_A) { - p = (unsigned char *)s->init_buf->data; - p = dtls1_set_message_header(s, p, SSL3_MT_HELLO_REQUEST, 0, 0, 0); - - s->state = SSL3_ST_SW_HELLO_REQ_B; - /* number of bytes to write */ - s->init_num = DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* - * no need to buffer this message, since there are no retransmit - * requests for it - */ - } - - /* SSL3_ST_SW_HELLO_REQ_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} - int dtls1_send_hello_verify_request(SSL *s) { unsigned int msg_len; @@ -921,8 +924,9 @@ int dtls1_send_hello_verify_request(SSL *s) buf = (unsigned char *)s->init_buf->data; msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]); - *(p++) = s->version >> 8; - *(p++) = s->version & 0xFF; + /* Always use DTLS 1.0 version: see RFC 6347 */ + *(p++) = DTLS1_VERSION >> 8; + *(p++) = DTLS1_VERSION & 0xFF; if (s->ctx->app_gen_cookie_cb == NULL || s->ctx->app_gen_cookie_cb(s, s->d1->cookie, @@ -951,788 +955,3 @@ int dtls1_send_hello_verify_request(SSL *s) /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); } - -int dtls1_send_server_hello(SSL *s) -{ - unsigned char *buf; - unsigned char *p, *d; - int i; - unsigned int sl; - unsigned long l; - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { - buf = (unsigned char *)s->init_buf->data; - p = s->s3->server_random; - ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE); - /* Do the message type and length last */ - d = p = &(buf[DTLS1_HM_HEADER_LENGTH]); - - *(p++) = s->version >> 8; - *(p++) = s->version & 0xff; - - /* Random stuff */ - memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - - /* - * now in theory we have 3 options to sending back the session id. - * If it is a re-use, we send back the old session-id, if it is a new - * session, we send back the new session-id or we send back a 0 - * length session-id if we want it to be single use. Currently I will - * not implement the '0' length session-id 12-Jan-98 - I'll now - * support the '0' length stuff. - */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) - s->session->session_id_length = 0; - - sl = s->session->session_id_length; - if (sl > sizeof s->session->session_id) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); - return -1; - } - *(p++) = sl; - memcpy(p, s->session->session_id, sl); - p += sl; - - /* put the cipher */ - if (s->s3->tmp.new_cipher == NULL) - return -1; - i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p); - p += i; - - /* put the compression method */ -#ifdef OPENSSL_NO_COMP - *(p++) = 0; -#else - if (s->s3->tmp.new_compression == NULL) - *(p++) = 0; - else - *(p++) = s->s3->tmp.new_compression->id; -#endif - -#ifndef OPENSSL_NO_TLSEXT - if (ssl_prepare_serverhello_tlsext(s) <= 0) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT); - return -1; - } - if ((p = - ssl_add_serverhello_tlsext(s, p, - buf + SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); - return -1; - } -#endif - - /* do the header */ - l = (p - d); - d = buf; - - d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l); - - s->state = SSL3_ST_SW_SRVR_HELLO_B; - /* number of bytes to write */ - s->init_num = p - buf; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SRVR_HELLO_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} - -int dtls1_send_server_done(SSL *s) -{ - unsigned char *p; - - if (s->state == SSL3_ST_SW_SRVR_DONE_A) { - p = (unsigned char *)s->init_buf->data; - - /* do the header */ - p = dtls1_set_message_header(s, p, SSL3_MT_SERVER_DONE, 0, 0, 0); - - s->state = SSL3_ST_SW_SRVR_DONE_B; - /* number of bytes to write */ - s->init_num = DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SRVR_DONE_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} - -int dtls1_send_server_key_exchange(SSL *s) -{ -#ifndef OPENSSL_NO_RSA - unsigned char *q; - int j, num; - RSA *rsa; - unsigned char md_buf[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; - unsigned int u; -#endif -#ifndef OPENSSL_NO_DH - DH *dh = NULL, *dhp; -#endif -#ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh = NULL, *ecdhp; - unsigned char *encodedPoint = NULL; - int encodedlen = 0; - int curve_id = 0; - BN_CTX *bn_ctx = NULL; -#endif - EVP_PKEY *pkey; - unsigned char *p, *d; - int al, i; - unsigned long type; - int n; - CERT *cert; - BIGNUM *r[4]; - int nr[4], kn; - BUF_MEM *buf; - EVP_MD_CTX md_ctx; - - EVP_MD_CTX_init(&md_ctx); - if (s->state == SSL3_ST_SW_KEY_EXCH_A) { - type = s->s3->tmp.new_cipher->algorithm_mkey; - cert = s->cert; - - buf = s->init_buf; - - r[0] = r[1] = r[2] = r[3] = NULL; - n = 0; -#ifndef OPENSSL_NO_RSA - if (type & SSL_kRSA) { - rsa = cert->rsa_tmp; - if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) { - rsa = s->cert->rsa_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3-> - tmp.new_cipher)); - if (rsa == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_ERROR_GENERATING_TMP_RSA_KEY); - goto f_err; - } - RSA_up_ref(rsa); - cert->rsa_tmp = rsa; - } - if (rsa == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_MISSING_TMP_RSA_KEY); - goto f_err; - } - r[0] = rsa->n; - r[1] = rsa->e; - s->s3->tmp.use_rsa_tmp = 1; - } else -#endif -#ifndef OPENSSL_NO_DH - if (type & SSL_kEDH) { - dhp = cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp = s->cert->dh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3-> - tmp.new_cipher)); - if (dhp == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - - if (s->s3->tmp.dh != NULL) { - DH_free(dh); - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((dh = DHparams_dup(dhp)) == NULL) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - - s->s3->tmp.dh = dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) { - if (!DH_generate_key(dh)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_DH_LIB); - goto err; - } - } else { - dh->pub_key = BN_dup(dhp->pub_key); - dh->priv_key = BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_DH_LIB); - goto err; - } - } - r[0] = dh->p; - r[1] = dh->g; - r[2] = dh->pub_key; - } else -#endif -#ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) { - const EC_GROUP *group; - - ecdhp = cert->ecdh_tmp; - if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) { - ecdhp = s->cert->ecdh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s-> - s3->tmp.new_cipher)); - } - if (ecdhp == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } - - if (s->s3->tmp.ecdh != NULL) { - EC_KEY_free(s->s3->tmp.ecdh); - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - /* Duplicate the ECDH structure. */ - if (ecdhp == NULL) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - s->s3->tmp.ecdh = ecdh; - if ((EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL) || - (s->options & SSL_OP_SINGLE_ECDH_USE)) { - if (!EC_KEY_generate_key(ecdh)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_ECDH_LIB); - goto err; - } - } - - if (((group = EC_KEY_get0_group(ecdh)) == NULL) || - (EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && - (EC_GROUP_get_degree(group) > 163)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); - goto err; - } - - /* - * XXX: For now, we only support ephemeral ECDH keys over named - * (not generic) curves. For supported named curves, curve_id is - * non-zero. - */ - if ((curve_id = - tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) - == 0) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); - goto err; - } - - /* - * Encode the public key. First check the size of encoding and - * allocate memory accordingly. - */ - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encodedlen * sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } - - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encodedlen, bn_ctx); - - if (encodedlen == 0) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - BN_CTX_free(bn_ctx); - bn_ctx = NULL; - - /* - * XXX: For now, we only support named (not generic) curves in - * ECDH ephemeral key exchanges. In this situation, we need four - * additional bytes to encode the entire ServerECDHParams - * structure. - */ - n = 4 + encodedlen; - - /* - * We'll generate the serverKeyExchange message explicitly so we - * can set these to NULLs - */ - r[0] = NULL; - r[1] = NULL; - r[2] = NULL; - r[3] = NULL; - } else -#endif /* !OPENSSL_NO_ECDH */ -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { - /* - * reserve size for record length and PSK identity hint - */ - n += 2 + strlen(s->ctx->psk_identity_hint); - } else -#endif /* !OPENSSL_NO_PSK */ - { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); - goto f_err; - } - for (i = 0; r[i] != NULL; i++) { - nr[i] = BN_num_bytes(r[i]); - n += 2 + nr[i]; - } - - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { - if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, NULL)) - == NULL) { - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - kn = EVP_PKEY_size(pkey); - } else { - pkey = NULL; - kn = 0; - } - - if (!BUF_MEM_grow_clean(buf, n + DTLS1_HM_HEADER_LENGTH + kn)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_BUF); - goto err; - } - d = (unsigned char *)s->init_buf->data; - p = &(d[DTLS1_HM_HEADER_LENGTH]); - - for (i = 0; r[i] != NULL; i++) { - s2n(nr[i], p); - BN_bn2bin(r[i], p); - p += nr[i]; - } - -#ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) { - /* - * XXX: For now, we only support named (not generic) curves. In - * this situation, the serverKeyExchange message has: [1 byte - * CurveType], [2 byte CurveName] [1 byte length of encoded - * point], followed by the actual encoded point itself - */ - *p = NAMED_CURVE_TYPE; - p += 1; - *p = 0; - p += 1; - *p = curve_id; - p += 1; - *p = encodedlen; - p += 1; - memcpy((unsigned char *)p, - (unsigned char *)encodedPoint, encodedlen); - OPENSSL_free(encodedPoint); - encodedPoint = NULL; - p += encodedlen; - } -#endif - -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { - /* copy PSK identity hint */ - s2n(strlen(s->ctx->psk_identity_hint), p); - strncpy((char *)p, s->ctx->psk_identity_hint, - strlen(s->ctx->psk_identity_hint)); - p += strlen(s->ctx->psk_identity_hint); - } -#endif - - /* not anonymous */ - if (pkey != NULL) { - /* - * n is the length of the params, they start at - * &(d[DTLS1_HM_HEADER_LENGTH]) and p points to the space at the - * end. - */ -#ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) { - q = md_buf; - j = 0; - for (num = 2; num > 0; num--) { - EVP_DigestInit_ex(&md_ctx, (num == 2) - ? s->ctx->md5 : s->ctx->sha1, NULL); - EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]), - SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]), - SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx, &(d[DTLS1_HM_HEADER_LENGTH]), - n); - EVP_DigestFinal_ex(&md_ctx, q, (unsigned int *)&i); - q += i; - j += i; - } - if (RSA_sign(NID_md5_sha1, md_buf, j, - &(p[2]), &u, pkey->pkey.rsa) <= 0) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_RSA); - goto err; - } - s2n(u, p); - n += u + 2; - } else -#endif -#if !defined(OPENSSL_NO_DSA) - if (pkey->type == EVP_PKEY_DSA) { - /* lets do DSS */ - EVP_SignInit_ex(&md_ctx, EVP_dss1(), NULL); - EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]), - SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]), - SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx, &(d[DTLS1_HM_HEADER_LENGTH]), n); - if (!EVP_SignFinal(&md_ctx, &(p[2]), - (unsigned int *)&i, pkey)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_DSA); - goto err; - } - s2n(i, p); - n += i + 2; - } else -#endif -#if !defined(OPENSSL_NO_ECDSA) - if (pkey->type == EVP_PKEY_EC) { - /* let's do ECDSA */ - EVP_SignInit_ex(&md_ctx, EVP_ecdsa(), NULL); - EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]), - SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]), - SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx, &(d[DTLS1_HM_HEADER_LENGTH]), n); - if (!EVP_SignFinal(&md_ctx, &(p[2]), - (unsigned int *)&i, pkey)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_LIB_ECDSA); - goto err; - } - s2n(i, p); - n += i + 2; - } else -#endif - { - /* Is this error check actually needed? */ - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - SSL_R_UNKNOWN_PKEY_TYPE); - goto f_err; - } - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_SERVER_KEY_EXCHANGE, n, 0, n); - - /* - * we should now have things packed up, so lets send it off - */ - s->init_num = n + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - s->state = SSL3_ST_SW_KEY_EXCH_B; - EVP_MD_CTX_cleanup(&md_ctx); - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: -#ifndef OPENSSL_NO_ECDH - if (encodedPoint != NULL) - OPENSSL_free(encodedPoint); - BN_CTX_free(bn_ctx); -#endif - EVP_MD_CTX_cleanup(&md_ctx); - return (-1); -} - -int dtls1_send_certificate_request(SSL *s) -{ - unsigned char *p, *d; - int i, j, nl, off, n; - STACK_OF(X509_NAME) *sk = NULL; - X509_NAME *name; - BUF_MEM *buf; - unsigned int msg_len; - - if (s->state == SSL3_ST_SW_CERT_REQ_A) { - buf = s->init_buf; - - d = p = (unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); - - /* get the list of acceptable cert types */ - p++; - n = ssl3_get_req_cert_type(s, p); - d[0] = n; - p += n; - n++; - - off = n; - p += 2; - n += 2; - - sk = SSL_get_client_CA_list(s); - nl = 0; - if (sk != NULL) { - for (i = 0; i < sk_X509_NAME_num(sk); i++) { - name = sk_X509_NAME_value(sk, i); - j = i2d_X509_NAME(name, NULL); - if (!BUF_MEM_grow_clean - (buf, DTLS1_HM_HEADER_LENGTH + n + j + 2)) { - SSLerr(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST, - ERR_R_BUF_LIB); - goto err; - } - p = (unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH + n]); - if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) { - s2n(j, p); - i2d_X509_NAME(name, &p); - n += 2 + j; - nl += 2 + j; - } else { - d = p; - i2d_X509_NAME(name, &p); - j -= 2; - s2n(j, d); - j += 2; - n += j; - nl += j; - } - } - } - /* else no CA names */ - p = (unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH + off]); - s2n(nl, p); - - d = (unsigned char *)buf->data; - *(d++) = SSL3_MT_CERTIFICATE_REQUEST; - l2n3(n, d); - s2n(s->d1->handshake_write_seq, d); - s->d1->handshake_write_seq++; - - /* - * we should now have things packed up, so lets send it off - */ - - s->init_num = n + DTLS1_HM_HEADER_LENGTH; - s->init_off = 0; -#ifdef NETSCAPE_HANG_BUG -/* XXX: what to do about this? */ - p = (unsigned char *)s->init_buf->data + s->init_num; - - /* do the header */ - *(p++) = SSL3_MT_SERVER_DONE; - *(p++) = 0; - *(p++) = 0; - *(p++) = 0; - s->init_num += 4; -#endif - - /* XDTLS: set message header ? */ - msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; - dtls1_set_message_header(s, (void *)s->init_buf->data, - SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, - msg_len); - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state = SSL3_ST_SW_CERT_REQ_B; - } - - /* SSL3_ST_SW_CERT_REQ_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); - err: - return (-1); -} - -int dtls1_send_server_certificate(SSL *s) -{ - unsigned long l; - X509 *x; - - if (s->state == SSL3_ST_SW_CERT_A) { - x = ssl_get_server_send_cert(s); - if (x == NULL) { - /* VRS: allow null cert if auth == KRB5 */ - if ((s->s3->tmp.new_cipher->algorithm_mkey != SSL_kKRB5) || - (s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5)) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE, - ERR_R_INTERNAL_ERROR); - return (0); - } - } - - l = dtls1_output_cert_chain(s, x); - if (!l) { - SSLerr(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); - return (0); - } - s->state = SSL3_ST_SW_CERT_B; - s->init_num = (int)l; - s->init_off = 0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_CERT_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} - -#ifndef OPENSSL_NO_TLSEXT -int dtls1_send_newsession_ticket(SSL *s) -{ - if (s->state == SSL3_ST_SW_SESSION_TICKET_A) { - unsigned char *p, *senc, *macstart; - int len, slen; - unsigned int hlen, msg_len; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; - SSL_CTX *tctx = s->initial_ctx; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char key_name[16]; - - /* get session encoding length */ - slen = i2d_SSL_SESSION(s->session, NULL); - /* - * Some length values are 16 bits, so forget it if session is too - * long - */ - if (slen > 0xFF00) - return -1; - /* - * Grow buffer if need be: the length calculation is as follows 12 - * (DTLS handshake message header) + 4 (ticket lifetime hint) + 2 - * (ticket length) + 16 (key name) + max_iv_len (iv length) + - * session_length + max_enc_block_size (max encrypted session length) - * + max_md_size (HMAC). - */ - if (!BUF_MEM_grow(s->init_buf, - DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH + - EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) - return -1; - senc = OPENSSL_malloc(slen); - if (!senc) - return -1; - p = senc; - i2d_SSL_SESSION(s->session, &p); - - p = (unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]); - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); - /* - * Initialize HMAC and cipher contexts. If callback present it does - * all the work otherwise use generated values from parent ctx. - */ - if (tctx->tlsext_ticket_key_cb) { - if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, - &hctx, 1) < 0) { - OPENSSL_free(senc); - return -1; - } - } else { - RAND_pseudo_bytes(iv, 16); - EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, - tctx->tlsext_tick_aes_key, iv); - HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, - tlsext_tick_md(), NULL); - memcpy(key_name, tctx->tlsext_tick_key_name, 16); - } - l2n(s->session->tlsext_tick_lifetime_hint, p); - /* Skip ticket length for now */ - p += 2; - /* Output key name */ - macstart = p; - memcpy(p, key_name, 16); - p += 16; - /* output IV */ - memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); - p += EVP_CIPHER_CTX_iv_length(&ctx); - /* Encrypt session data */ - EVP_EncryptUpdate(&ctx, p, &len, senc, slen); - p += len; - EVP_EncryptFinal(&ctx, p, &len); - p += len; - EVP_CIPHER_CTX_cleanup(&ctx); - - HMAC_Update(&hctx, macstart, p - macstart); - HMAC_Final(&hctx, p, &hlen); - HMAC_CTX_cleanup(&hctx); - - p += hlen; - /* Now write out lengths: p points to end of data written */ - /* Total length */ - len = p - (unsigned char *)(s->init_buf->data); - /* Ticket length */ - p = (unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4; - s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p); - - /* number of bytes to write */ - s->init_num = len; - s->state = SSL3_ST_SW_SESSION_TICKET_B; - s->init_off = 0; - OPENSSL_free(senc); - - /* XDTLS: set message header ? */ - msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; - dtls1_set_message_header(s, (void *)s->init_buf->data, - SSL3_MT_NEWSESSION_TICKET, msg_len, 0, - msg_len); - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SESSION_TICKET_B */ - return (dtls1_do_write(s, SSL3_RT_HANDSHAKE)); -} -#endif diff --git a/ssl/dtls1.h b/ssl/dtls1.h index 8deb299a7c85..30bbcf278a43 100644 --- a/ssl/dtls1.h +++ b/ssl/dtls1.h @@ -84,11 +84,15 @@ extern "C" { #endif # define DTLS1_VERSION 0xFEFF -# define DTLS_MAX_VERSION DTLS1_VERSION +# define DTLS1_2_VERSION 0xFEFD +# define DTLS_MAX_VERSION DTLS1_2_VERSION # define DTLS1_VERSION_MAJOR 0xFE # define DTLS1_BAD_VER 0x0100 +/* Special value for method supporting multiple versions */ +# define DTLS_ANY_VERSION 0x1FFFF + # if 0 /* this alert description is not specified anywhere... */ # define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 diff --git a/ssl/heartbeat_test.c b/ssl/heartbeat_test.c index 3cec8b163fae..7623c36ccf18 100644 --- a/ssl/heartbeat_test.c +++ b/ssl/heartbeat_test.c @@ -272,8 +272,8 @@ static int test_dtls1_not_bleeding() { SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" - " "; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = + " Not bleeding, sixteen spaces of padding" " "; const int payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; @@ -294,9 +294,9 @@ static int test_dtls1_not_bleeding_empty_payload() * Three-byte pad at the beginning for type and payload length, plus a * NUL at the end */ - unsigned char payload_buf[4 + MIN_PADDING_SIZE]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; + memset(payload_buf, ' ', MIN_PADDING_SIZE + 3); + payload_buf[MIN_PADDING_SIZE + 3] = '\0'; payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; @@ -311,7 +311,8 @@ static int test_dtls1_heartbleed() { SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " HEARTBLEED "; + unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS] = + " HEARTBLEED "; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -328,9 +329,9 @@ static int test_dtls1_heartbleed_empty_payload() * Excluding the NUL at the end, one byte short of type + payload length * + minimum padding */ - unsigned char payload_buf[MIN_PADDING_SIZE + 3]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; + memset(payload_buf, ' ', MIN_PADDING_SIZE + 2); + payload_buf[MIN_PADDING_SIZE + 2] = '\0'; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -363,8 +364,8 @@ static int test_tls1_not_bleeding() { SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" - " "; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = + " Not bleeding, sixteen spaces of padding" " "; const int payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; @@ -385,9 +386,9 @@ static int test_tls1_not_bleeding_empty_payload() * Three-byte pad at the beginning for type and payload length, plus a * NUL at the end */ - unsigned char payload_buf[4 + MIN_PADDING_SIZE]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; + memset(payload_buf, ' ', MIN_PADDING_SIZE + 3); + payload_buf[MIN_PADDING_SIZE + 3] = '\0'; payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; @@ -402,7 +403,8 @@ static int test_tls1_heartbleed() { SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " HEARTBLEED "; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] = + " HEARTBLEED "; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -419,9 +421,9 @@ static int test_tls1_heartbleed_empty_payload() * Excluding the NUL at the end, one byte short of type + payload length * + minimum padding */ - unsigned char payload_buf[MIN_PADDING_SIZE + 3]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; + memset(payload_buf, ' ', MIN_PADDING_SIZE + 2); + payload_buf[MIN_PADDING_SIZE + 2] = '\0'; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 3766567c8f80..e4e707cf687e 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -279,7 +279,6 @@ static int ssl23_no_ssl2_ciphers(SSL *s) int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len) { int send_time = 0; - if (len < 4) return 0; if (server) @@ -303,6 +302,7 @@ static int ssl23_client_hello(SSL *s) unsigned long l; int ssl2_compat; int version = 0, version_major, version_minor; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; @@ -368,6 +368,8 @@ static int ssl23_client_hello(SSL *s) || s->tlsext_opaque_prf_input != NULL) ssl2_compat = 0; # endif + if (s->cert->cli_ext.meths_count != 0) + ssl2_compat = 0; } #endif @@ -387,6 +389,10 @@ static int ssl23_client_hello(SSL *s) if (version == TLS1_2_VERSION) { version_major = TLS1_2_VERSION_MAJOR; version_minor = TLS1_2_VERSION_MINOR; + } else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL23_CLIENT_HELLO, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + return -1; } else if (version == TLS1_1_VERSION) { version_major = TLS1_1_VERSION_MAJOR; version_minor = TLS1_1_VERSION_MINOR; @@ -542,9 +548,9 @@ static int ssl23_client_hello(SSL *s) } if ((p = ssl_add_clienthello_tlsext(s, p, - buf + - SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { + buf + SSL3_RT_MAX_PLAIN_LENGTH, + &al)) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); SSLerr(SSL_F_SSL23_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); return -1; } @@ -598,10 +604,13 @@ static int ssl23_client_hello(SSL *s) if (ssl2_compat) s->msg_callback(1, SSL2_VERSION, 0, s->init_buf->data + 2, ret - 2, s, s->msg_callback_arg); - else + else { + s->msg_callback(1, version, SSL3_RT_HEADER, s->init_buf->data, 5, + s, s->msg_callback_arg); s->msg_callback(1, version, SSL3_RT_HANDSHAKE, s->init_buf->data + 5, ret - 5, s, s->msg_callback_arg); + } } return ret; @@ -749,9 +758,12 @@ static int ssl23_get_server_hello(SSL *s) cb(s, SSL_CB_READ_ALERT, j); } - if (s->msg_callback) + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_HEADER, p, 5, s, + s->msg_callback_arg); s->msg_callback(0, s->version, SSL3_RT_ALERT, p + 5, 2, s, s->msg_callback_arg); + } s->rwstate = SSL_NOTHING; SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_AD_REASON_OFFSET + p[6]); diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index 50f98dced44f..470bd3d94f29 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -402,6 +402,11 @@ int ssl23_get_client_hello(SSL *s) /* ensure that TLS_MAX_VERSION is up-to-date */ OPENSSL_assert(s->version <= TLS_MAX_VERSION); + if (s->version < TLS1_2_VERSION && tls1_suiteb(s)) { + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + goto err; + } #ifdef OPENSSL_FIPS if (FIPS_mode() && (s->version < TLS1_VERSION)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO, diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c index b23b083153fb..69da6b1421df 100644 --- a/ssl/s2_clnt.c +++ b/ssl/s2_clnt.c @@ -418,19 +418,19 @@ static int get_server_hello(SSL *s) return (-1); } } else { -# ifdef undef +# if 0 /* very bad */ memset(s->session->session_id, 0, SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES); s->session->session_id_length = 0; - */ # endif - /* - * we need to do this in case we were trying to reuse a client - * session but others are already reusing it. If this was a new - * 'blank' session ID, the session-id length will still be 0 - */ - if (s->session->session_id_length > 0) { + + /* + * we need to do this in case we were trying to reuse a client + * session but others are already reusing it. If this was a new + * 'blank' session ID, the session-id length will still be 0 + */ + if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s, 0)) { ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); return (-1); diff --git a/ssl/s2_lib.c b/ssl/s2_lib.c index 7e3674a685fb..d55b93f76bb7 100644 --- a/ssl/s2_lib.c +++ b/ssl/s2_lib.c @@ -435,10 +435,7 @@ const SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p) ((unsigned long)p[1] << 8L) | (unsigned long)p[2]; c.id = id; cp = OBJ_bsearch_ssl_cipher_id(&c, ssl2_ciphers, SSL2_NUM_CIPHERS); - if ((cp == NULL) || (cp->valid == 0)) - return NULL; - else - return cp; + return cp; } int ssl2_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p) diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 107b460f27b6..019e21cd0274 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -158,13 +158,12 @@ int ssl3_do_write(SSL *s, int type) int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) { - unsigned char *p, *d; + unsigned char *p; int i; unsigned long l; if (s->state == a) { - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + p = ssl_handshake_start(s); i = s->method->ssl3_enc->final_finish_mac(s, sender, slen, @@ -173,7 +172,6 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) return 0; s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); - p += i; l = i; /* @@ -196,17 +194,12 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) */ l &= 0xffff; #endif - - *(d++) = SSL3_MT_FINISHED; - l2n3(l, d); - s->init_num = (int)l + 4; - s->init_off = 0; - + ssl_set_handshake_header(s, SSL3_MT_FINISHED, l); s->state = b; } /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #ifndef OPENSSL_NO_NEXTPROTONEG @@ -248,7 +241,7 @@ int ssl3_get_finished(SSL *s, int a, int b) #ifdef OPENSSL_NO_NEXTPROTONEG /* * the mac has already been generated when we received the change cipher - * spec message and is in s->s3->tmp.peer_finish_md. + * spec message and is in s->s3->tmp.peer_finish_md */ #endif @@ -326,84 +319,20 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b) return (ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC)); } -static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) -{ - int n; - unsigned char *p; - - n = i2d_X509(x, NULL); - if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) { - SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF, ERR_R_BUF_LIB); - return (-1); - } - p = (unsigned char *)&(buf->data[*l]); - l2n3(n, p); - i2d_X509(x, &p); - *l += n + 3; - - return (0); -} - -unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) +unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) { unsigned char *p; - int i; - unsigned long l = 7; - BUF_MEM *buf; - int no_chain; - - if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) - no_chain = 1; - else - no_chain = 0; + unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s); - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - buf = s->init_buf; - if (!BUF_MEM_grow_clean(buf, 10)) { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_BUF_LIB); - return (0); - } - if (x != NULL) { - if (no_chain) { - if (ssl3_add_cert_to_buf(buf, &l, x)) - return (0); - } else { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx, s->ctx->cert_store, x, NULL)) { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_X509_LIB); - return (0); - } - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { - x = sk_X509_value(xs_ctx.chain, i); - - if (ssl3_add_cert_to_buf(buf, &l, x)) { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - } - /* Thawte special :-) */ - for (i = 0; i < sk_X509_num(s->ctx->extra_certs); i++) { - x = sk_X509_value(s->ctx->extra_certs, i); - if (ssl3_add_cert_to_buf(buf, &l, x)) - return (0); - } + if (!ssl_add_cert_chain(s, cpk, &l)) + return 0; - l -= 7; - p = (unsigned char *)&(buf->data[4]); + l -= 3 + SSL_HM_HEADER_LENGTH(s); + p = ssl_handshake_start(s); l2n3(l, p); l += 3; - p = (unsigned char *)&(buf->data[0]); - *(p++) = SSL3_MT_CERTIFICATE; - l2n3(l, p); - l += 4; - return (l); + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l); + return l + SSL_HM_HEADER_LENGTH(s); } /* @@ -477,17 +406,6 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } - if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && - (st1 == SSL3_ST_SR_CERT_A) && (stn == SSL3_ST_SR_CERT_B)) { - /* - * At this point we have got an MS SGC second client hello (maybe - * we should always allow the client to start a new handshake?). - * We need to restart the mac. Don't increment - * {num,total}_renegotiations because we have not completed the - * handshake. - */ - ssl3_init_finished_mac(s); - } s->s3->tmp.message_type = *(p++); @@ -578,7 +496,18 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey) ret = SSL_PKEY_GOST94; } else if (i == NID_id_GostR3410_2001 || i == NID_id_GostR3410_2001_cc) { ret = SSL_PKEY_GOST01; + } else if (x && (i == EVP_PKEY_DH || i == EVP_PKEY_DHX)) { + /* + * For DH two cases: DH certificate signed with RSA and DH + * certificate signed with DSA. + */ + i = X509_certificate_type(x, pk); + if (i & EVP_PKS_RSA) + ret = SSL_PKEY_DH_RSA; + else if (i & EVP_PKS_DSA) + ret = SSL_PKEY_DH_DSA; } + err: if (!pkey) EVP_PKEY_free(pk); diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 2fb71f277e9c..a0edcef90ada 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -125,7 +125,7 @@ int tls1_cbc_remove_padding(const SSL *s, unsigned padding_length, good, to_check, i; const unsigned overhead = 1 /* padding length byte */ + mac_size; /* Check if version requires explicit IV */ - if (s->version >= TLS1_1_VERSION || s->version == DTLS1_BAD_VER) { + if (SSL_USE_EXPLICIT_IV(s)) { /* * These lengths are all public so we can test them in non-constant * time. diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 35ad1217a655..6af145a8b744 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -317,11 +317,11 @@ int ssl3_connect(SSL *s) s->state = SSL3_ST_CR_SESSION_TICKET_A; } #endif - } else + } else { s->state = SSL3_ST_CR_CERT_A; + } s->init_num = 0; break; - case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: #ifndef OPENSSL_NO_TLSEXT @@ -675,6 +675,7 @@ int ssl3_client_hello(SSL *s) unsigned char *p, *d; int i; unsigned long l; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; @@ -697,15 +698,64 @@ int ssl3_client_hello(SSL *s) if (!ssl_get_new_session(s, 0)) goto err; } + if (s->method->version == DTLS_ANY_VERSION) { + /* Determine which DTLS version to use */ + int options = s->options; + /* If DTLS 1.2 disabled correct the version number */ + if (options & SSL_OP_NO_DTLSv1_2) { + if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + goto err; + } + /* + * Disabling all versions is silly: return an error. + */ + if (options & SSL_OP_NO_DTLSv1) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_WRONG_SSL_VERSION); + goto err; + } + /* + * Update method so we don't use any DTLS 1.2 features. + */ + s->method = DTLSv1_client_method(); + s->version = DTLS1_VERSION; + } else { + /* + * We only support one version: update method + */ + if (options & SSL_OP_NO_DTLSv1) + s->method = DTLSv1_2_client_method(); + s->version = DTLS1_2_VERSION; + } + s->client_version = s->version; + } /* else use the pre-loaded session */ p = s->s3->client_random; - if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0) + /* + * for DTLS if client_random is initialized, reuse it, we are + * required to use same upon reply to HelloVerify + */ + if (SSL_IS_DTLS(s)) { + size_t idx; + i = 1; + for (idx = 0; idx < sizeof(s->s3->client_random); idx++) { + if (p[idx]) { + i = 0; + break; + } + } + } else + i = 1; + + if (i && ssl_fill_hello_random(s, 0, p, + sizeof(s->s3->client_random)) <= 0) goto err; /* Do the message type and length last */ - d = p = &(buf[4]); + d = p = ssl_handshake_start(s); /*- * version indicates the negotiated version: for example from @@ -765,6 +815,17 @@ int ssl3_client_hello(SSL *s) p += i; } + /* cookie stuff for DTLS */ + if (SSL_IS_DTLS(s)) { + if (s->d1->cookie_len > sizeof(s->d1->cookie)) { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + *(p++) = s->d1->cookie_len; + memcpy(p, s->d1->cookie, s->d1->cookie_len); + p += s->d1->cookie_len; + } + /* Ciphers supported */ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]), 0); if (i == 0) { @@ -809,27 +870,21 @@ int ssl3_client_hello(SSL *s) goto err; } if ((p = - ssl_add_clienthello_tlsext(s, p, - buf + SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { + ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH, + &al)) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } #endif - l = (p - d); - d = buf; - *(d++) = SSL3_MT_CLIENT_HELLO; - l2n3(l, d); - + l = p - d; + ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); s->state = SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num = p - buf; - s->init_off = 0; } /* SSL3_ST_CW_CLNT_HELLO_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: s->state = SSL_ST_ERR; return (-1); @@ -839,13 +894,20 @@ int ssl3_get_server_hello(SSL *s) { STACK_OF(SSL_CIPHER) *sk; const SSL_CIPHER *c; + CERT *ct = s->cert; unsigned char *p, *d; - int i, al, ok; + int i, al = SSL_AD_INTERNAL_ERROR, ok; unsigned int j; long n; #ifndef OPENSSL_NO_COMP SSL_COMP *comp; #endif + /* + * Hello verify request and/or server hello version may not match so set + * first packet if we're negotiating version. + */ + if (SSL_IS_DTLS(s)) + s->first_packet = 1; n = s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, @@ -854,7 +916,8 @@ int ssl3_get_server_hello(SSL *s) if (!ok) return ((int)n); - if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { + s->first_packet = 0; if (s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { if (s->d1->send_cookie == 0) { s->s3->tmp.reuse_message = 1; @@ -875,6 +938,28 @@ int ssl3_get_server_hello(SSL *s) } d = p = (unsigned char *)s->init_msg; + if (s->method->version == DTLS_ANY_VERSION) { + /* Work out correct protocol version to use */ + int hversion = (p[0] << 8) | p[1]; + int options = s->options; + if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2)) + s->method = DTLSv1_2_client_method(); + else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } else if (hversion == DTLS1_VERSION && !(options & SSL_OP_NO_DTLSv1)) + s->method = DTLSv1_client_method(); + else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); + s->version = hversion; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version = s->method->version; + } if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); @@ -951,7 +1036,6 @@ int ssl3_get_server_hello(SSL *s) */ if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s, 0)) { - al = SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -966,21 +1050,16 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } - /* TLS v1.2 only ciphersuites require v1.2 or later */ - if ((c->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_version(s) < TLS1_2_VERSION)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED); - goto f_err; - } -#ifndef OPENSSL_NO_SRP - if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) && - !(s->srp_ctx.srp_Mask & SSL_kSRP)) { + /* + * If it is a disabled cipher we didn't send it in client hello, so + * return an error. + */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || c->algorithm_auth & ct->mask_a) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; } -#endif /* OPENSSL_NO_SRP */ p += ssl_put_cipher_by_char(s, NULL, NULL); sk = ssl_get_ciphers_by_id(s); @@ -1013,14 +1092,11 @@ int ssl3_get_server_hello(SSL *s) } s->s3->tmp.new_cipher = c; /* - * Don't digest cached records if TLS v1.2: we may need them for client + * Don't digest cached records if no sigalgs: we may need them for client * authentication. */ - if (TLS1_get_version(s) < TLS1_2_VERSION - && !ssl3_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; + if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s)) goto f_err; - } /* lets get the compression algorithm */ /* COMPRESSION */ #ifdef OPENSSL_NO_COMP @@ -1035,7 +1111,6 @@ int ssl3_get_server_hello(SSL *s) * using compression. */ if (s->session->compress_meth != 0) { - al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1068,16 +1143,9 @@ int ssl3_get_server_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ - if (s->version >= SSL3_VERSION) { - if (!ssl_parse_serverhello_tlsext(s, &p, d, n, &al)) { - /* 'al' set by ssl_parse_serverhello_tlsext */ - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT); - goto f_err; - } - if (ssl_check_serverhello_tlsext(s) <= 0) { - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT); - goto err; - } + if (!ssl_parse_serverhello_tlsext(s, &p, d, n)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT); + goto err; } #endif @@ -1240,6 +1308,14 @@ int ssl3_get_server_certificate(SSL *s) } if (need_cert) { + int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (exp_idx >= 0 && i != exp_idx) { + x = NULL; + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto f_err; + } sc->peer_cert_type = i; CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); /* @@ -1267,7 +1343,6 @@ int ssl3_get_server_certificate(SSL *s) x = NULL; ret = 1; - if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); @@ -1326,7 +1401,7 @@ int ssl3_get_key_exchange(SSL *s) * Can't skip server key exchange if this is an ephemeral * ciphersuite. */ - if (alg_k & (SSL_kEDH | SSL_kEECDH)) { + if (alg_k & (SSL_kDHE | SSL_kECDHE)) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); al = SSL_AD_UNEXPECTED_MESSAGE; goto f_err; @@ -1718,9 +1793,16 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto f_err; } + /* + * Check curve is one of our preferences, if not server has sent an + * invalid curve. ECParameters is 3 bytes. + */ + if (!tls1_check_curve(s, p, 3)) { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE); + goto f_err; + } - if ((*p != NAMED_CURVE_TYPE) || - ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)) { + if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); @@ -1808,29 +1890,16 @@ int ssl3_get_key_exchange(SSL *s) /* if it was signed, check the signature */ if (pkey != NULL) { - if (TLS1_get_version(s) >= TLS1_2_VERSION) { - int sigalg; + if (SSL_USE_SIGALGS(s)) { + int rv; if (2 > n) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT); goto f_err; } - - sigalg = tls12_get_sigid(pkey); - /* Should never happen */ - if (sigalg == -1) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + rv = tls12_check_peer_sigalg(&md, s, p, pkey); + if (rv == -1) goto err; - } - /* Check key type is consistent with signature */ - if (sigalg != (int)p[1]) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_WRONG_SIGNATURE_TYPE); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - md = tls12_get_hash(p[0]); - if (md == NULL) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNKNOWN_DIGEST); + else if (rv == 0) { goto f_err; } #ifdef SSL_DEBUG @@ -1858,8 +1927,7 @@ int ssl3_get_key_exchange(SSL *s) goto f_err; } #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA - && TLS1_get_version(s) < TLS1_2_VERSION) { + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { int num; unsigned int size; @@ -1909,7 +1977,10 @@ int ssl3_get_key_exchange(SSL *s) } else { /* aNULL, aSRP or kPSK do not need public keys */ if (!(alg_a & (SSL_aNULL | SSL_aSRP)) && !(alg_k & SSL_kPSK)) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + /* Might be wrong key type, check it */ + if (ssl3_check_cert_and_algorithm(s)) + /* Otherwise this shouldn't happen */ + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } /* still data left over */ @@ -2002,12 +2073,21 @@ int ssl3_get_certificate_request(SSL *s) /* get the certificate types */ ctype_num = *(p++); - if (ctype_num > SSL3_CT_NUMBER) + if (s->cert->ctypes) { + OPENSSL_free(s->cert->ctypes); + s->cert->ctypes = NULL; + } + if (ctype_num > SSL3_CT_NUMBER) { + /* If we exceed static buffer copy all to cert structure */ + s->cert->ctypes = OPENSSL_malloc(ctype_num); + memcpy(s->cert->ctypes, p, ctype_num); + s->cert->ctype_num = (size_t)ctype_num; ctype_num = SSL3_CT_NUMBER; + } for (i = 0; i < ctype_num; i++) s->s3->tmp.ctype[i] = p[i]; - p += ctype_num; - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + p += p[-1]; + if (SSL_USE_SIGALGS(s)) { n2s(p, llen); /* * Check we have enough room for signature algorithms and following @@ -2019,12 +2099,22 @@ int ssl3_get_certificate_request(SSL *s) SSL_R_DATA_LENGTH_TOO_LONG); goto err; } - if ((llen & 1) || !tls1_process_sigalgs(s, p, llen)) { + /* Clear certificate digests and validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) { + s->cert->pkeys[i].digest = NULL; + s->cert->pkeys[i].valid_flags = 0; + } + if ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_SIGNATURE_ALGORITHMS_ERROR); goto err; } + if (!tls1_process_sigalgs(s)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); + goto err; + } p += llen; } @@ -2299,9 +2389,28 @@ int ssl3_get_server_done(SSL *s) return (ret); } +#ifndef OPENSSL_NO_DH +static DH *get_server_static_dh_key(SESS_CERT *scert) +{ + DH *dh_srvr = NULL; + EVP_PKEY *spkey = NULL; + int idx = scert->peer_cert_type; + + if (idx >= 0) + spkey = X509_get_pubkey(scert->peer_pkeys[idx].x509); + if (spkey) { + dh_srvr = EVP_PKEY_get1_DH(spkey); + EVP_PKEY_free(spkey); + } + if (dh_srvr == NULL) + SSLerr(SSL_F_GET_SERVER_STATIC_DH_KEY, ERR_R_INTERNAL_ERROR); + return dh_srvr; +} +#endif + int ssl3_send_client_key_exchange(SSL *s) { - unsigned char *p, *d; + unsigned char *p; int n; unsigned long alg_k; #ifndef OPENSSL_NO_RSA @@ -2321,8 +2430,7 @@ int ssl3_send_client_key_exchange(SSL *s) #endif if (s->state == SSL3_ST_CW_KEY_EXCH_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + p = ssl_handshake_start(s); alg_k = s->s3->tmp.new_cipher->algorithm_mkey; @@ -2533,33 +2641,45 @@ int ssl3_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_DH else if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) { DH *dh_srvr, *dh_clnt; + SESS_CERT *scert = s->session->sess_cert; - if (s->session->sess_cert == NULL) { + if (scert == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); goto err; } - if (s->session->sess_cert->peer_dh_tmp != NULL) - dh_srvr = s->session->sess_cert->peer_dh_tmp; - else { - /* we get them from the cert */ - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); - goto err; + if (scert->peer_dh_tmp != NULL) { + dh_srvr = scert->peer_dh_tmp; + } else { + dh_srvr = get_server_static_dh_key(scert); + if (dh_srvr == NULL) + goto err; } - /* generate a new random key */ - if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - if (!DH_generate_key(dh_clnt)) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - DH_free(dh_clnt); - goto err; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + /* Use client certificate key */ + EVP_PKEY *clkey = s->cert->key->privatekey; + dh_clnt = NULL; + if (clkey) + dh_clnt = EVP_PKEY_get1_DH(clkey); + if (dh_clnt == NULL) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* generate a new random key */ + if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); + goto err; + } + if (!DH_generate_key(dh_clnt)) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); + DH_free(dh_clnt); + goto err; + } } /* @@ -2568,6 +2688,8 @@ int ssl3_send_client_key_exchange(SSL *s) */ n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); + if (scert->peer_dh_tmp == NULL) + DH_free(dh_srvr); if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); @@ -2584,11 +2706,15 @@ int ssl3_send_client_key_exchange(SSL *s) /* clean up */ memset(p, 0, n); - /* send off the data */ - n = BN_num_bytes(dh_clnt->pub_key); - s2n(n, p); - BN_bn2bin(dh_clnt->pub_key, p); - n += 2; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) + n = 0; + else { + /* send off the data */ + n = BN_num_bytes(dh_clnt->pub_key); + s2n(n, p); + BN_bn2bin(dh_clnt->pub_key, p); + n += 2; + } DH_free(dh_clnt); } @@ -3014,17 +3140,12 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - *(d++) = SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n, d); - + ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); s->state = SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num = n + 4; - s->init_off = 0; } /* SSL3_ST_CW_KEY_EXCH_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: #ifndef OPENSSL_NO_ECDH BN_CTX_free(bn_ctx); @@ -3040,7 +3161,7 @@ int ssl3_send_client_key_exchange(SSL *s) int ssl3_send_client_verify(SSL *s) { - unsigned char *p, *d; + unsigned char *p; unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; EVP_PKEY *pkey; EVP_PKEY_CTX *pctx = NULL; @@ -3052,14 +3173,13 @@ int ssl3_send_client_verify(SSL *s) EVP_MD_CTX_init(&mctx); if (s->state == SSL3_ST_CW_CERT_VRFY_A) { - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + p = ssl_handshake_start(s); pkey = s->cert->key->privatekey; /* Create context from key and test if sha1 is allowed as digest */ pctx = EVP_PKEY_CTX_new(pkey, NULL); EVP_PKEY_sign_init(pctx); if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) > 0) { - if (TLS1_get_version(s) < TLS1_2_VERSION) + if (!SSL_USE_SIGALGS(s)) s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(data @@ -3071,7 +3191,7 @@ int ssl3_send_client_verify(SSL *s) * For TLS v1.2 send signature algorithm and signature using agreed * digest and cached handshake records. */ - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; const EVP_MD *md = s->cert->key->digest; @@ -3155,16 +3275,12 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } - *(d++) = SSL3_MT_CERTIFICATE_VERIFY; - l2n3(n, d); - + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); s->state = SSL3_ST_CW_CERT_VRFY_B; - s->init_num = (int)n + 4; - s->init_off = 0; } EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); @@ -3172,20 +3288,75 @@ int ssl3_send_client_verify(SSL *s) return (-1); } +/* + * Check a certificate can be used for client authentication. Currently check + * cert exists, if we have a suitable digest for TLS 1.2 if static DH client + * certificates can be used and optionally checks suitability for Suite B. + */ +static int ssl3_check_client_certificate(SSL *s) +{ + unsigned long alg_k; + if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey) + return 0; + /* If no suitable signature algorithm can't use certificate */ + if (SSL_USE_SIGALGS(s) && !s->cert->key->digest) + return 0; + /* + * If strict mode check suitability of chain before using it. This also + * adjusts suite B digest if necessary. + */ + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT && + !tls1_check_chain(s, NULL, NULL, NULL, -2)) + return 0; + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + /* See if we can use client certificate for fixed DH */ + if (alg_k & (SSL_kDHr | SSL_kDHd)) { + SESS_CERT *scert = s->session->sess_cert; + int i = scert->peer_cert_type; + EVP_PKEY *clkey = NULL, *spkey = NULL; + clkey = s->cert->key->privatekey; + /* If client key not DH assume it can be used */ + if (EVP_PKEY_id(clkey) != EVP_PKEY_DH) + return 1; + if (i >= 0) + spkey = X509_get_pubkey(scert->peer_pkeys[i].x509); + if (spkey) { + /* Compare server and client parameters */ + i = EVP_PKEY_cmp_parameters(clkey, spkey); + EVP_PKEY_free(spkey); + if (i != 1) + return 0; + } + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + } + return 1; +} + int ssl3_send_client_certificate(SSL *s) { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; int i; - unsigned long l; if (s->state == SSL3_ST_CW_CERT_A) { - if ((s->cert == NULL) || - (s->cert->key->x509 == NULL) || - (s->cert->key->privatekey == NULL)) - s->state = SSL3_ST_CW_CERT_B; - else + /* Let cert callback update client certificates if required */ + if (s->cert->cert_cb) { + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return -1; + } + if (i == 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; + return 0; + } + s->rwstate = SSL_NOTHING; + } + if (ssl3_check_client_certificate(s)) s->state = SSL3_ST_CW_CERT_C; + else + s->state = SSL3_ST_CW_CERT_B; } /* We need to get a client cert */ @@ -3215,6 +3386,8 @@ int ssl3_send_client_certificate(SSL *s) X509_free(x509); if (pkey != NULL) EVP_PKEY_free(pkey); + if (i && !ssl3_check_client_certificate(s)) + i = 0; if (i == 0) { if (s->version == SSL3_VERSION) { s->s3->tmp.cert_req = 0; @@ -3231,20 +3404,17 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_C) { s->state = SSL3_ST_CW_CERT_D; - l = ssl3_output_cert_chain(s, - (s->s3->tmp.cert_req == - 2) ? NULL : s->cert->key->x509); - if (!l) { + if (!ssl3_output_cert_chain(s, + (s->s3->tmp.cert_req == + 2) ? NULL : s->cert->key)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); s->state = SSL_ST_ERR; return 0; } - s->init_num = (int)l; - s->init_off = 0; } /* SSL3_ST_CW_CERT_D */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #define has_bits(i,m) (((i)&(m)) == (m)) @@ -3268,7 +3438,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* we don't have a certificate */ - if ((alg_a & (SSL_aDH | SSL_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) + if ((alg_a & (SSL_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) return (1); sc = s->session->sess_cert; @@ -3295,6 +3465,13 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else { return 1; } + } else if (alg_a & SSL_aECDSA) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_ECDSA_SIGNING_CERT); + goto f_err; + } else if (alg_k & (SSL_kECDHr | SSL_kECDHe)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_ECDH_CERT); + goto f_err; } #endif pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509); @@ -3345,22 +3522,33 @@ int ssl3_check_cert_and_algorithm(SSL *s) SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); goto f_err; } - if ((alg_k & SSL_kDHr) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { + if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) && + !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_RSA_CERT); goto f_err; } # ifndef OPENSSL_NO_DSA - if ((alg_k & SSL_kDHd) && !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { + if ((alg_k & SSL_kDHd) && !SSL_USE_SIGALGS(s) && + !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_DSA_CERT); goto f_err; } # endif - /* Check DHE only: static DH not implemented. */ - if (alg_k & SSL_kEDH) { - int dh_size = BN_num_bits(dh->p); + if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { + int dh_size; + if (alg_k & SSL_kDHE) { + dh_size = BN_num_bits(dh->p); + } else { + DH *dh_srvr = get_server_static_dh_key(sc); + if (dh_srvr == NULL) + goto f_err; + dh_size = BN_num_bits(dh_srvr->p); + DH_free(dh_srvr); + } + if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); @@ -3388,7 +3576,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & SSL_kEDH) { + if (alg_k & SSL_kDHE) { if (BN_num_bits(dh->p) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { /* We have a temporary DH key but it's too large. */ diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 152f40db582b..cda2d8c77603 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -374,6 +374,23 @@ int ssl3_change_cipher_state(SSL *s, int which) EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE)); +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) { + + int wh = which & SSL3_CC_WRITE ? + TLS1_RT_CRYPTO_WRITE : TLS1_RT_CRYPTO_READ; + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC, + mac_secret, EVP_MD_size(m), s, s->msg_callback_arg); + if (c->key_len) + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, + key, c->key_len, s, s->msg_callback_arg); + if (k) { + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_IV, + iv, k, s, s->msg_callback_arg); + } + } +#endif + OPENSSL_cleanse(&(exp_key[0]), sizeof(exp_key)); OPENSSL_cleanse(&(exp_iv[0]), sizeof(exp_iv)); EVP_MD_CTX_cleanup(&md); @@ -823,6 +840,9 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, EVP_MD_CTX ctx; int i, ret = 0; unsigned int n; +#ifdef OPENSSL_SSL_TRACE_CRYPTO + unsigned char *tmpout = out; +#endif EVP_MD_CTX_init(&ctx); for (i = 0; i < 3; i++) { @@ -841,6 +861,22 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, ret += n; } EVP_MD_CTX_cleanup(&ctx); + +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) { + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_PREMASTER, + p, len, s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_CLIENT_RANDOM, + s->s3->client_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_SERVER_RANDOM, + s->s3->server_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_MASTER, + tmpout, SSL3_MASTER_SECRET_SIZE, + s, s->msg_callback_arg); + } +#endif OPENSSL_cleanse(buf, sizeof buf); return (ret); } diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index de917d3f836f..ad9eeb6fd453 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -152,11 +152,6 @@ #include <openssl/objects.h> #include "ssl_locl.h" #include "kssl_lcl.h" -#ifndef OPENSSL_NO_TLSEXT -# ifndef OPENSSL_NO_EC -# include "../crypto/ec/ec_lcl.h" -# endif /* OPENSSL_NO_EC */ -#endif /* OPENSSL_NO_TLSEXT */ #include <openssl/md5.h> #ifndef OPENSSL_NO_DH # include <openssl/dh.h> @@ -351,7 +346,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 0C */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, SSL3_TXT_DH_DSS_DES_64_CBC_SHA, SSL3_CK_DH_DSS_DES_64_CBC_SHA, SSL_kDHd, @@ -367,7 +362,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 0D */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, SSL3_TXT_DH_DSS_DES_192_CBC3_SHA, SSL3_CK_DH_DSS_DES_192_CBC3_SHA, SSL_kDHd, @@ -383,7 +378,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 0E */ { - 0, /* not implemented (non-ephemeral DH) */ + 0, SSL3_TXT_DH_RSA_DES_40_CBC_SHA, SSL3_CK_DH_RSA_DES_40_CBC_SHA, SSL_kDHr, @@ -399,7 +394,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 0F */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, SSL3_TXT_DH_RSA_DES_64_CBC_SHA, SSL3_CK_DH_RSA_DES_64_CBC_SHA, SSL_kDHr, @@ -415,7 +410,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 10 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, SSL3_TXT_DH_RSA_DES_192_CBC3_SHA, SSL3_CK_DH_RSA_DES_192_CBC3_SHA, SSL_kDHr, @@ -902,7 +897,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { }, /* Cipher 30 */ { - 0, + 1, TLS1_TXT_DH_DSS_WITH_AES_128_SHA, TLS1_CK_DH_DSS_WITH_AES_128_SHA, SSL_kDHd, @@ -917,7 +912,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { }, /* Cipher 31 */ { - 0, + 1, TLS1_TXT_DH_RSA_WITH_AES_128_SHA, TLS1_CK_DH_RSA_WITH_AES_128_SHA, SSL_kDHr, @@ -993,7 +988,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { }, /* Cipher 36 */ { - 0, + 1, TLS1_TXT_DH_DSS_WITH_AES_256_SHA, TLS1_CK_DH_DSS_WITH_AES_256_SHA, SSL_kDHd, @@ -1009,7 +1004,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 37 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_AES_256_SHA, TLS1_CK_DH_RSA_WITH_AES_256_SHA, SSL_kDHr, @@ -1122,7 +1117,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 3E */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_DSS_WITH_AES_128_SHA256, TLS1_CK_DH_DSS_WITH_AES_128_SHA256, SSL_kDHd, @@ -1138,7 +1133,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 3F */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_AES_128_SHA256, TLS1_CK_DH_RSA_WITH_AES_128_SHA256, SSL_kDHr, @@ -1189,7 +1184,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 42 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_kDHd, @@ -1205,7 +1200,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 43 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_kDHr, @@ -1404,7 +1399,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 68 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_DSS_WITH_AES_256_SHA256, TLS1_CK_DH_DSS_WITH_AES_256_SHA256, SSL_kDHd, @@ -1420,7 +1415,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 69 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_AES_256_SHA256, TLS1_CK_DH_RSA_WITH_AES_256_SHA256, SSL_kDHr, @@ -1573,7 +1568,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { }, /* Cipher 85 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_kDHd, @@ -1589,7 +1584,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 86 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_kDHr, @@ -1739,7 +1734,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 97 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_DSS_WITH_SEED_SHA, TLS1_CK_DH_DSS_WITH_SEED_SHA, SSL_kDHd, @@ -1755,7 +1750,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher 98 */ { - 0, /* not implemented (non-ephemeral DH) */ + 1, TLS1_TXT_DH_RSA_WITH_SEED_SHA, TLS1_CK_DH_RSA_WITH_SEED_SHA, SSL_kDHr, @@ -1887,7 +1882,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher A0 */ { - 0, + 1, TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256, TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256, SSL_kDHr, @@ -1903,7 +1898,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher A1 */ { - 0, + 1, TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384, TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384, SSL_kDHr, @@ -1951,7 +1946,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher A4 */ { - 0, + 1, TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256, TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256, SSL_kDHd, @@ -1967,7 +1962,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { /* Cipher A5 */ { - 0, + 1, TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384, TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384, SSL_kDHd, @@ -2012,6 +2007,21 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = { 256, 256, }, +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + { + 1, + "SCSV", + SSL3_CK_SCSV, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0}, +#endif #ifndef OPENSSL_NO_ECDH /* Cipher C001 */ @@ -2899,6 +2909,10 @@ SSL3_ENC_METHOD SSLv3_enc_data = { (int (*)(SSL *, unsigned char *, size_t, const char *, size_t, const unsigned char *, size_t, int use_context))ssl_undefined_function, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write }; long ssl3_default_timeout(void) @@ -2932,6 +2946,20 @@ int ssl3_pending(const SSL *s) SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0; } +void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len) +{ + unsigned char *p = (unsigned char *)s->init_buf->data; + *(p++) = htype; + l2n3(len, p); + s->init_num = (int)len + SSL3_HM_HEADER_LENGTH; + s->init_off = 0; +} + +int ssl3_handshake_write(SSL *s) +{ + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); +} + int ssl3_new(SSL *s) { SSL3_STATE *s3; @@ -2988,6 +3016,11 @@ void ssl3_free(SSL *s) } if (s->s3->handshake_dgst) ssl3_free_digest_list(s); +#ifndef OPENSSL_NO_TLSEXT + if (s->s3->alpn_selected) + OPENSSL_free(s->s3->alpn_selected); +#endif + #ifndef OPENSSL_NO_SRP SSL_SRP_CTX_free(s); #endif @@ -3049,6 +3082,12 @@ void ssl3_clear(SSL *s) if (s->s3->handshake_dgst) { ssl3_free_digest_list(s); } +#if !defined(OPENSSL_NO_TLSEXT) + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } +#endif memset(s->s3, 0, sizeof *s->s3); s->s3->rbuf.buf = rp; s->s3->wbuf.buf = wp; @@ -3081,6 +3120,9 @@ static char *MS_CALLBACK srp_password_from_info_cb(SSL *s, void *arg) } #endif +static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, + size_t len); + long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) { int ret = 0; @@ -3309,8 +3351,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) # ifndef OPENSSL_NO_HEARTBEATS case SSL_CTRL_TLS_EXT_SEND_HEARTBEAT: - if (SSL_version(s) == DTLS1_VERSION - || SSL_version(s) == DTLS1_BAD_VER) + if (SSL_IS_DTLS(s)) ret = dtls1_heartbeat(s); else ret = tls1_heartbeat(s); @@ -3331,6 +3372,196 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) #endif /* !OPENSSL_NO_TLSEXT */ + case SSL_CTRL_CHAIN: + if (larg) + return ssl_cert_set1_chain(s->cert, (STACK_OF(X509) *)parg); + else + return ssl_cert_set0_chain(s->cert, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg) + return ssl_cert_add1_chain_cert(s->cert, (X509 *)parg); + else + return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + *(STACK_OF(X509) **)parg = s->cert->key->chain; + break; + + case SSL_CTRL_SELECT_CURRENT_CERT: + return ssl_cert_select_current(s->cert, (X509 *)parg); + + case SSL_CTRL_SET_CURRENT_CERT: + if (larg == SSL_CERT_SET_SERVER) { + CERT_PKEY *cpk; + const SSL_CIPHER *cipher; + if (!s->server) + return 0; + cipher = s->s3->tmp.new_cipher; + if (!cipher) + return 0; + /* + * No certificate for unauthenticated ciphersuites or using SRP + * authentication + */ + if (cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) + return 2; + cpk = ssl_get_server_send_pkey(s); + if (!cpk) + return 0; + s->cert->key = cpk; + return 1; + } + return ssl_cert_set_current(s->cert, larg); + +#ifndef OPENSSL_NO_EC + case SSL_CTRL_GET_CURVES: + { + unsigned char *clist; + size_t clistlen; + if (!s->session) + return 0; + clist = s->session->tlsext_ellipticcurvelist; + clistlen = s->session->tlsext_ellipticcurvelist_length / 2; + if (parg) { + size_t i; + int *cptr = parg; + unsigned int cid, nid; + for (i = 0; i < clistlen; i++) { + n2s(clist, cid); + nid = tls1_ec_curve_id2nid(cid); + if (nid != 0) + cptr[i] = nid; + else + cptr[i] = TLSEXT_nid_unknown | cid; + } + } + return (int)clistlen; + } + + case SSL_CTRL_SET_CURVES: + return tls1_set_curves(&s->tlsext_ellipticcurvelist, + &s->tlsext_ellipticcurvelist_length, + parg, larg); + + case SSL_CTRL_SET_CURVES_LIST: + return tls1_set_curves_list(&s->tlsext_ellipticcurvelist, + &s->tlsext_ellipticcurvelist_length, + parg); + + case SSL_CTRL_GET_SHARED_CURVE: + return tls1_shared_curve(s, larg); + +# ifndef OPENSSL_NO_ECDH + case SSL_CTRL_SET_ECDH_AUTO: + s->cert->ecdh_tmp_auto = larg; + return 1; +# endif +#endif + case SSL_CTRL_SET_SIGALGS: + return tls1_set_sigalgs(s->cert, parg, larg, 0); + + case SSL_CTRL_SET_SIGALGS_LIST: + return tls1_set_sigalgs_list(s->cert, parg, 0); + + case SSL_CTRL_SET_CLIENT_SIGALGS: + return tls1_set_sigalgs(s->cert, parg, larg, 1); + + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(s->cert, parg, 1); + + case SSL_CTRL_GET_CLIENT_CERT_TYPES: + { + const unsigned char **pctype = parg; + if (s->server || !s->s3->tmp.cert_req) + return 0; + if (s->cert->ctypes) { + if (pctype) + *pctype = s->cert->ctypes; + return (int)s->cert->ctype_num; + } + if (pctype) + *pctype = (unsigned char *)s->s3->tmp.ctype; + return s->s3->tmp.ctype_num; + } + + case SSL_CTRL_SET_CLIENT_CERT_TYPES: + if (!s->server) + return 0; + return ssl3_set_req_cert_type(s->cert, parg, larg); + + case SSL_CTRL_BUILD_CERT_CHAIN: + return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg); + + case SSL_CTRL_SET_VERIFY_CERT_STORE: + return ssl_cert_set_cert_store(s->cert, parg, 0, larg); + + case SSL_CTRL_SET_CHAIN_CERT_STORE: + return ssl_cert_set_cert_store(s->cert, parg, 1, larg); + + case SSL_CTRL_GET_PEER_SIGNATURE_NID: + if (SSL_USE_SIGALGS(s)) { + if (s->session && s->session->sess_cert) { + const EVP_MD *sig; + sig = s->session->sess_cert->peer_key->digest; + if (sig) { + *(int *)parg = EVP_MD_type(sig); + return 1; + } + } + return 0; + } + /* Might want to do something here for other versions */ + else + return 0; + + case SSL_CTRL_GET_SERVER_TMP_KEY: + if (s->server || !s->session || !s->session->sess_cert) + return 0; + else { + SESS_CERT *sc; + EVP_PKEY *ptmp; + int rv = 0; + sc = s->session->sess_cert; +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_ECDH) + if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp && !sc->peer_ecdh_tmp) + return 0; +#endif + ptmp = EVP_PKEY_new(); + if (!ptmp) + return 0; + if (0) ; +#ifndef OPENSSL_NO_RSA + else if (sc->peer_rsa_tmp) + rv = EVP_PKEY_set1_RSA(ptmp, sc->peer_rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH + else if (sc->peer_dh_tmp) + rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp); +#endif +#ifndef OPENSSL_NO_ECDH + else if (sc->peer_ecdh_tmp) + rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp); +#endif + if (rv) { + *(EVP_PKEY **)parg = ptmp; + return 1; + } + EVP_PKEY_free(ptmp); + return 0; + } +#ifndef OPENSSL_NO_EC + case SSL_CTRL_GET_EC_POINT_FORMATS: + { + SSL_SESSION *sess = s->session; + const unsigned char **pformat = parg; + if (!sess || !sess->tlsext_ecpointformatlist) + return 0; + *pformat = sess->tlsext_ecpointformatlist; + return (int)sess->tlsext_ecpointformatlist_length; + } +#endif + case SSL_CTRL_CHECK_PROTO_VERSION: /* * For library-internal use; checks that the current protocol is the @@ -3606,6 +3837,47 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) ctx->srp_ctx.strength = larg; break; # endif + +# ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_CURVES: + return tls1_set_curves(&ctx->tlsext_ellipticcurvelist, + &ctx->tlsext_ellipticcurvelist_length, + parg, larg); + + case SSL_CTRL_SET_CURVES_LIST: + return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist, + &ctx->tlsext_ellipticcurvelist_length, + parg); +# ifndef OPENSSL_NO_ECDH + case SSL_CTRL_SET_ECDH_AUTO: + ctx->cert->ecdh_tmp_auto = larg; + return 1; +# endif +# endif + case SSL_CTRL_SET_SIGALGS: + return tls1_set_sigalgs(ctx->cert, parg, larg, 0); + + case SSL_CTRL_SET_SIGALGS_LIST: + return tls1_set_sigalgs_list(ctx->cert, parg, 0); + + case SSL_CTRL_SET_CLIENT_SIGALGS: + return tls1_set_sigalgs(ctx->cert, parg, larg, 1); + + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(ctx->cert, parg, 1); + + case SSL_CTRL_SET_CLIENT_CERT_TYPES: + return ssl3_set_req_cert_type(ctx->cert, parg, larg); + + case SSL_CTRL_BUILD_CERT_CHAIN: + return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg); + + case SSL_CTRL_SET_VERIFY_CERT_STORE: + return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg); + + case SSL_CTRL_SET_CHAIN_CERT_STORE: + return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg); + #endif /* !OPENSSL_NO_TLSEXT */ /* A Thawte special :-) */ @@ -3618,7 +3890,10 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) break; case SSL_CTRL_GET_EXTRA_CHAIN_CERTS: - *(STACK_OF(X509) **)parg = ctx->extra_certs; + if (ctx->extra_certs == NULL && larg == 0) + *(STACK_OF(X509) **)parg = ctx->cert->key->chain; + else + *(STACK_OF(X509) **)parg = ctx->extra_certs; break; case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS: @@ -3628,6 +3903,28 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) } break; + case SSL_CTRL_CHAIN: + if (larg) + return ssl_cert_set1_chain(ctx->cert, (STACK_OF(X509) *)parg); + else + return ssl_cert_set0_chain(ctx->cert, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg) + return ssl_cert_add1_chain_cert(ctx->cert, (X509 *)parg); + else + return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + *(STACK_OF(X509) **)parg = ctx->cert->key->chain; + break; + + case SSL_CTRL_SELECT_CURRENT_CERT: + return ssl_cert_select_current(ctx->cert, (X509 *)parg); + + case SSL_CTRL_SET_CURRENT_CERT: + return ssl_cert_set_current(ctx->cert, larg); + default: return (0); } @@ -3702,7 +3999,6 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) break; # endif #endif - default: return (0); } @@ -3726,10 +4022,7 @@ const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p) if (cp == NULL) fprintf(stderr, "Unknown cipher ID %x\n", (p[0] << 8) | p[1]); #endif - if (cp == NULL || cp->valid == 0) - return NULL; - else - return cp; + return cp; } int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p) @@ -3752,11 +4045,6 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, SSL_CIPHER *c, *ret = NULL; STACK_OF(SSL_CIPHER) *prio, *allow; int i, ii, ok; -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_EC) - unsigned int j; - int ec_ok, ec_nid; - unsigned char ec_search1 = 0, ec_search2 = 0; -#endif CERT *cert; unsigned long alg_k, alg_a, mask_k, mask_a, emask_k, emask_a; @@ -3789,7 +4077,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, } #endif - if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) { prio = srvr; allow = clnt; } else { @@ -3797,12 +4085,13 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, allow = srvr; } + tls1_set_cert_validity(s); + for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) { c = sk_SSL_CIPHER_value(prio, i); - /* Skip TLS v1.2 only ciphersuites if lower than v1.2 */ - if ((c->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_version(s) < TLS1_2_VERSION)) + /* Skip TLS v1.2 only ciphersuites if not supported */ + if ((c->algorithm_ssl & SSL_TLSV1_2) && !SSL_USE_TLS1_2_CIPHERS(s)) continue; ssl_set_cert_masks(cert, c); @@ -3857,194 +4146,13 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, #ifndef OPENSSL_NO_TLSEXT # ifndef OPENSSL_NO_EC - if ( - /* - * if we are considering an ECC cipher suite that uses our - * certificate - */ - (alg_a & SSL_aECDSA || alg_a & SSL_aECDH) - /* and we have an ECC certificate */ - && (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL) - /* - * and the client specified a Supported Point Formats - * extension - */ - && ((s->session->tlsext_ecpointformatlist_length > 0) - && (s->session->tlsext_ecpointformatlist != NULL)) - /* and our certificate's point is compressed */ - && ((s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info != NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info->key != - NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info-> - key->public_key != NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info-> - key->public_key->data != NULL) - && - ((* - (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info-> - key->public_key->data) == POINT_CONVERSION_COMPRESSED) - || - (* - (s->cert->pkeys[SSL_PKEY_ECC].x509->cert_info-> - key->public_key->data) == - POINT_CONVERSION_COMPRESSED + 1) - ) - ) - ) { - ec_ok = 0; - /* - * if our certificate's curve is over a field type that the - * client does not support then do not allow this cipher suite to - * be negotiated - */ - if ((s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != - NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec-> - group->meth != NULL) - && - (EC_METHOD_get_field_type - (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec-> - group->meth) == NID_X9_62_prime_field) - ) { - for (j = 0; j < s->session->tlsext_ecpointformatlist_length; - j++) { - if (s->session->tlsext_ecpointformatlist[j] == - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime) { - ec_ok = 1; - break; - } - } - } else - if (EC_METHOD_get_field_type - (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec-> - group->meth) == NID_X9_62_characteristic_two_field) { - for (j = 0; j < s->session->tlsext_ecpointformatlist_length; - j++) { - if (s->session->tlsext_ecpointformatlist[j] == - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2) { - ec_ok = 1; - break; - } - } - } - ok = ok && ec_ok; - } - if ( - /* - * if we are considering an ECC cipher suite that uses our - * certificate - */ - (alg_a & SSL_aECDSA || alg_a & SSL_aECDH) - /* and we have an ECC certificate */ - && (s->cert->pkeys[SSL_PKEY_ECC].x509 != NULL) - /* - * and the client specified an EllipticCurves extension - */ - && ((s->session->tlsext_ellipticcurvelist_length > 0) - && (s->session->tlsext_ellipticcurvelist != NULL)) - ) { - ec_ok = 0; - if ((s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec != NULL) - && (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec->group != - NULL) - ) { - ec_nid = - EC_GROUP_get_curve_name(s->cert-> - pkeys[SSL_PKEY_ECC].privatekey-> - pkey.ec->group); - if ((ec_nid == 0) - && (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey. - ec->group->meth != NULL) - ) { - if (EC_METHOD_get_field_type - (s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey. - ec->group->meth) == NID_X9_62_prime_field) { - ec_search1 = 0xFF; - ec_search2 = 0x01; - } else - if (EC_METHOD_get_field_type - (s->cert->pkeys[SSL_PKEY_ECC].privatekey-> - pkey.ec->group->meth) == - NID_X9_62_characteristic_two_field) { - ec_search1 = 0xFF; - ec_search2 = 0x02; - } - } else { - ec_search1 = 0x00; - ec_search2 = tls1_ec_nid2curve_id(ec_nid); - } - if ((ec_search1 != 0) || (ec_search2 != 0)) { - for (j = 0; - j < s->session->tlsext_ellipticcurvelist_length / 2; - j++) { - if ((s->session->tlsext_ellipticcurvelist[2 * j] == - ec_search1) - && (s->session->tlsext_ellipticcurvelist[2 * j + - 1] == - ec_search2)) { - ec_ok = 1; - break; - } - } - } - } - ok = ok && ec_ok; - } # ifndef OPENSSL_NO_ECDH - if ( - /* - * if we are considering an ECC cipher suite that uses an - * ephemeral EC key - */ - (alg_k & SSL_kEECDH) - /* and we have an ephemeral EC key */ - && (s->cert->ecdh_tmp != NULL) - /* - * and the client specified an EllipticCurves extension - */ - && ((s->session->tlsext_ellipticcurvelist_length > 0) - && (s->session->tlsext_ellipticcurvelist != NULL)) - ) { - ec_ok = 0; - if (s->cert->ecdh_tmp->group != NULL) { - ec_nid = EC_GROUP_get_curve_name(s->cert->ecdh_tmp->group); - if ((ec_nid == 0) - && (s->cert->ecdh_tmp->group->meth != NULL) - ) { - if (EC_METHOD_get_field_type - (s->cert->ecdh_tmp->group->meth) == - NID_X9_62_prime_field) { - ec_search1 = 0xFF; - ec_search2 = 0x01; - } else - if (EC_METHOD_get_field_type - (s->cert->ecdh_tmp->group->meth) == - NID_X9_62_characteristic_two_field) { - ec_search1 = 0xFF; - ec_search2 = 0x02; - } - } else { - ec_search1 = 0x00; - ec_search2 = tls1_ec_nid2curve_id(ec_nid); - } - if ((ec_search1 != 0) || (ec_search2 != 0)) { - for (j = 0; - j < s->session->tlsext_ellipticcurvelist_length / 2; - j++) { - if ((s->session->tlsext_ellipticcurvelist[2 * j] == - ec_search1) - && (s->session->tlsext_ellipticcurvelist[2 * j + - 1] == - ec_search2)) { - ec_ok = 1; - break; - } - } - } - } - ok = ok && ec_ok; - } + /* + * if we are considering an ECC cipher suite that uses an ephemeral + * EC key check it + */ + if (alg_k & SSL_kEECDH) + ok = ok && tls1_check_ec_tmp_key(s, c->id); # endif /* OPENSSL_NO_ECDH */ # endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_NO_TLSEXT */ @@ -4071,8 +4179,41 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, int ssl3_get_req_cert_type(SSL *s, unsigned char *p) { int ret = 0; + const unsigned char *sig; + size_t i, siglen; + int have_rsa_sign = 0, have_dsa_sign = 0; +#ifndef OPENSSL_NO_ECDSA + int have_ecdsa_sign = 0; +#endif + int nostrict = 1; unsigned long alg_k; + /* If we have custom certificate types set, use them */ + if (s->cert->ctypes) { + memcpy(p, s->cert->ctypes, s->cert->ctype_num); + return (int)s->cert->ctype_num; + } + /* get configured sigalgs */ + siglen = tls12_get_psigalgs(s, &sig); + if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT) + nostrict = 0; + for (i = 0; i < siglen; i += 2, sig += 2) { + switch (sig[1]) { + case TLSEXT_signature_rsa: + have_rsa_sign = 1; + break; + + case TLSEXT_signature_dsa: + have_dsa_sign = 1; + break; +#ifndef OPENSSL_NO_ECDSA + case TLSEXT_signature_ecdsa: + have_ecdsa_sign = 1; + break; +#endif + } + } + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; #ifndef OPENSSL_NO_GOST @@ -4088,10 +4229,16 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p) #ifndef OPENSSL_NO_DH if (alg_k & (SSL_kDHr | SSL_kEDH)) { # ifndef OPENSSL_NO_RSA - p[ret++] = SSL3_CT_RSA_FIXED_DH; + /* + * Since this refers to a certificate signed with an RSA algorithm, + * only check for rsa signing in strict mode. + */ + if (nostrict || have_rsa_sign) + p[ret++] = SSL3_CT_RSA_FIXED_DH; # endif # ifndef OPENSSL_NO_DSA - p[ret++] = SSL3_CT_DSS_FIXED_DH; + if (nostrict || have_dsa_sign) + p[ret++] = SSL3_CT_DSS_FIXED_DH; # endif } if ((s->version == SSL3_VERSION) && @@ -4105,15 +4252,19 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p) } #endif /* !OPENSSL_NO_DH */ #ifndef OPENSSL_NO_RSA - p[ret++] = SSL3_CT_RSA_SIGN; + if (have_rsa_sign) + p[ret++] = SSL3_CT_RSA_SIGN; #endif #ifndef OPENSSL_NO_DSA - p[ret++] = SSL3_CT_DSS_SIGN; + if (have_dsa_sign) + p[ret++] = SSL3_CT_DSS_SIGN; #endif #ifndef OPENSSL_NO_ECDH if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->version >= TLS1_VERSION)) { - p[ret++] = TLS_CT_RSA_FIXED_ECDH; - p[ret++] = TLS_CT_ECDSA_FIXED_ECDH; + if (nostrict || have_rsa_sign) + p[ret++] = TLS_CT_RSA_FIXED_ECDH; + if (nostrict || have_ecdsa_sign) + p[ret++] = TLS_CT_ECDSA_FIXED_ECDH; } #endif @@ -4123,12 +4274,31 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p) * need to check for SSL_kECDH or SSL_kEECDH */ if (s->version >= TLS1_VERSION) { - p[ret++] = TLS_CT_ECDSA_SIGN; + if (have_ecdsa_sign) + p[ret++] = TLS_CT_ECDSA_SIGN; } #endif return (ret); } +static int ssl3_set_req_cert_type(CERT *c, const unsigned char *p, size_t len) +{ + if (c->ctypes) { + OPENSSL_free(c->ctypes); + c->ctypes = NULL; + } + if (!p || !len) + return 1; + if (len > 0xff) + return 0; + c->ctypes = OPENSSL_malloc(len); + if (!c->ctypes) + return 0; + memcpy(c->ctypes, p, len); + c->ctype_num = len; + return 1; +} + int ssl3_shutdown(SSL *s) { int ret; @@ -4310,14 +4480,14 @@ int ssl3_renegotiate_check(SSL *s) } /* - * If we are using TLS v1.2 or later and default SHA1+MD5 algorithms switch - * to new SHA256 PRF and handshake macs + * If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and + * handshake macs if required. */ long ssl_get_algorithm2(SSL *s) { long alg2 = s->s3->tmp.new_cipher->algorithm2; - if (s->method->version == TLS1_2_VERSION && - alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF)) + if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF + && alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF)) return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256; return alg2; } diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 25cf929a55d6..603c285ac499 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -118,6 +118,20 @@ #include <openssl/buffer.h> #include <openssl/rand.h> +#ifndef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 +#endif + +#if defined(OPENSSL_SMALL_FOOTPRINT) || \ + !( defined(AES_ASM) && ( \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) || \ + defined(__INTEL__) ) \ + ) +# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0 +#endif + static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment); static int ssl3_get_record(SSL *s); @@ -183,7 +197,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) * operation returns the whole packet at once (as long as it fits into * the buffer). */ - if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { if (left == 0 && extend) return 0; if (left > 0 && n > left) @@ -246,9 +260,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) if (i <= 0) { rb->left = left; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && - SSL_version(s) != DTLS1_VERSION - && SSL_version(s) != DTLS1_BAD_VER) + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) if (len + left == 0) ssl3_release_read_buffer(s); return (i); @@ -259,8 +271,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend) * underlying transport protocol is message oriented as opposed to * byte oriented as in the TLS case. */ - if (SSL_version(s) == DTLS1_VERSION - || SSL_version(s) == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { if (n > left) n = left; /* makes the while condition false */ } @@ -331,6 +342,9 @@ static int ssl3_get_record(SSL *s) s->rstate = SSL_ST_READ_BODY; p = s->packet; + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, + s->msg_callback_arg); /* Pull apart the header into the SSL3_RECORD */ rr->type = *(p++); @@ -621,8 +635,13 @@ int ssl3_do_compress(SSL *ssl) int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { const unsigned char *buf = buf_; + int tot; unsigned int n, nw; - int i, tot; +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + unsigned int max_send_fragment; +#endif + SSL3_BUFFER *wb = &(s->s3->wbuf); + int i; s->rwstate = SSL_NOTHING; OPENSSL_assert(s->s3->wnum <= INT_MAX); @@ -653,6 +672,154 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) return (-1); } + /* + * first check if there is a SSL3_BUFFER still being written out. This + * will happen with non blocking IO + */ + if (wb->left != 0) { + i = ssl3_write_pending(s, type, &buf[tot], s->s3->wpend_tot); + if (i <= 0) { + /* XXX should we ssl3_release_write_buffer if i<0? */ + s->s3->wnum = tot; + return i; + } + tot += i; /* this might be last fragment */ + } +#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK + /* + * Depending on platform multi-block can deliver several *times* + * better performance. Downside is that it has to allocate + * jumbo buffer to accomodate up to 8 records, but the + * compromise is considered worthy. + */ + if (type == SSL3_RT_APPLICATION_DATA && + len >= 4 * (int)(max_send_fragment = s->max_send_fragment) && + s->compress == NULL && s->msg_callback == NULL && + SSL_USE_EXPLICIT_IV(s) && + EVP_CIPHER_flags(s->enc_write_ctx->cipher) & + EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) { + unsigned char aad[13]; + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; + int packlen; + + /* minimize address aliasing conflicts */ + if ((max_send_fragment & 0xfff) == 0) + max_send_fragment -= 512; + + if (tot == 0 || wb->buf == NULL) { /* allocate jumbo buffer */ + ssl3_release_write_buffer(s); + + packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE, + max_send_fragment, NULL); + + if (len >= 8 * (int)max_send_fragment) + packlen *= 8; + else + packlen *= 4; + + wb->buf = OPENSSL_malloc(packlen); + if (!wb->buf) { + SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_MALLOC_FAILURE); + return -1; + } + wb->len = packlen; + } else if (tot == len) { /* done? */ + OPENSSL_free(wb->buf); /* free jumbo buffer */ + wb->buf = NULL; + return tot; + } + + n = (len - tot); + for (;;) { + if (n < 4 * max_send_fragment) { + OPENSSL_free(wb->buf); /* free jumbo buffer */ + wb->buf = NULL; + break; + } + + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) { + s->s3->wnum = tot; + return i; + } + } + + if (n >= 8 * max_send_fragment) + nw = max_send_fragment * (mb_param.interleave = 8); + else + nw = max_send_fragment * (mb_param.interleave = 4); + + memcpy(aad, s->s3->write_sequence, 8); + aad[8] = type; + aad[9] = (unsigned char)(s->version >> 8); + aad[10] = (unsigned char)(s->version); + aad[11] = 0; + aad[12] = 0; + mb_param.out = NULL; + mb_param.inp = aad; + mb_param.len = nw; + + packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_AAD, + sizeof(mb_param), &mb_param); + + if (packlen <= 0 || packlen > (int)wb->len) { /* never happens */ + OPENSSL_free(wb->buf); /* free jumbo buffer */ + wb->buf = NULL; + break; + } + + mb_param.out = wb->buf; + mb_param.inp = &buf[tot]; + mb_param.len = nw; + + if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + sizeof(mb_param), &mb_param) <= 0) + return -1; + + s->s3->write_sequence[7] += mb_param.interleave; + if (s->s3->write_sequence[7] < mb_param.interleave) { + int j = 6; + while (j >= 0 && (++s->s3->write_sequence[j--]) == 0) ; + } + + wb->offset = 0; + wb->left = packlen; + + s->s3->wpend_tot = nw; + s->s3->wpend_buf = &buf[tot]; + s->s3->wpend_type = type; + s->s3->wpend_ret = nw; + + i = ssl3_write_pending(s, type, &buf[tot], nw); + if (i <= 0) { + if (i < 0 && (!s->wbio || !BIO_should_retry(s->wbio))) { + OPENSSL_free(wb->buf); + wb->buf = NULL; + } + s->s3->wnum = tot; + return i; + } + if (i == (int)n) { + OPENSSL_free(wb->buf); /* free jumbo buffer */ + wb->buf = NULL; + return tot + i; + } + n -= i; + tot += i; + } + } else +#endif + if (tot == len) { /* done? */ + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + + return tot; + } + n = (len - tot); for (;;) { if (n > s->max_send_fragment) @@ -662,6 +829,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) i = do_ssl3_write(s, type, &(buf[tot]), nw, 0); if (i <= 0) { + /* XXX should we ssl3_release_write_buffer if i<0? */ s->s3->wnum = tot; return i; } @@ -675,6 +843,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) */ s->s3->empty_fragment_done = 0; + if ((i == (int)n) && s->mode & SSL_MODE_RELEASE_BUFFERS && + !SSL_IS_DTLS(s)) + ssl3_release_write_buffer(s); + return tot + i; } @@ -809,8 +981,8 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, /* field where we are to write out packet length */ plen = p; p += 2; - /* Explicit IV length, block ciphers and TLS version 1.1 or later */ - if (s->enc_write_ctx && s->version >= TLS1_1_VERSION) { + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) { int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); if (mode == EVP_CIPH_CBC_MODE) { eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); @@ -873,6 +1045,10 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, /* record length after mac and block padding */ s2n(wr->length, plen); + if (s->msg_callback) + s->msg_callback(1, 0, SSL3_RT_HEADER, plen - 5, 5, s, + s->msg_callback_arg); + /* * we should now have wr->data pointing to the encrypted data, which is * wr->length long @@ -936,10 +1112,6 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, if (i == wb->left) { wb->left = 0; wb->offset += i; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && - SSL_version(s) != DTLS1_VERSION - && SSL_version(s) != DTLS1_BAD_VER) - ssl3_release_write_buffer(s); s->rwstate = SSL_NOTHING; return (s->s3->wpend_ret); } else if (i <= 0) { diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 3a5f71d745fa..acd3b9e964a2 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -293,7 +293,7 @@ int ssl3_accept(SSL *s) } s->init_num = 0; - s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE; + s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY; s->s3->flags &= ~SSL3_FLAGS_CCS_OK; /* * Should have been reset by ssl3_get_finished, too. @@ -360,12 +360,12 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown = 0; - if (s->rwstate != SSL_X509_LOOKUP) { - ret = ssl3_get_client_hello(s); - if (ret <= 0) - goto end; - } + ret = ssl3_get_client_hello(s); + if (ret <= 0) + goto end; #ifndef OPENSSL_NO_SRP + s->state = SSL3_ST_SR_CLNT_HELLO_D; + case SSL3_ST_SR_CLNT_HELLO_D: { int al; if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) { @@ -477,7 +477,7 @@ int ssl3_accept(SSL *s) /* SRP: send ServerKeyExchange */ || (alg_k & SSL_kSRP) #endif - || (alg_k & (SSL_kDHr | SSL_kDHd | SSL_kEDH)) + || (alg_k & SSL_kEDH) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL @@ -590,21 +590,13 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - /* Check for second client hello (MS SGC) */ - ret = ssl3_check_client_hello(s); - if (ret <= 0) - goto end; - if (ret == 2) - s->state = SSL3_ST_SR_CLNT_HELLO_C; - else { - if (s->s3->tmp.cert_request) { - ret = ssl3_get_client_certificate(s); - if (ret <= 0) - goto end; - } - s->init_num = 0; - s->state = SSL3_ST_SR_KEY_EXCH_A; + if (s->s3->tmp.cert_request) { + ret = ssl3_get_client_certificate(s); + if (ret <= 0) + goto end; } + s->init_num = 0; + s->state = SSL3_ST_SR_KEY_EXCH_A; break; case SSL3_ST_SR_KEY_EXCH_A: @@ -628,13 +620,13 @@ int ssl3_accept(SSL *s) s->state = SSL3_ST_SR_FINISHED_A; #endif s->init_num = 0; - } else if (TLS1_get_version(s) >= TLS1_2_VERSION) { + } else if (SSL_USE_SIGALGS(s)) { s->state = SSL3_ST_SR_CERT_VRFY_A; s->init_num = 0; if (!s->session->peer) break; /* - * For TLS v1.2 freeze the handshake buffer at this point and + * For sigalgs freeze the handshake buffer at this point and * digest cached records. */ if (!s->s3->handshake_buffer) { @@ -898,86 +890,33 @@ int ssl3_accept(SSL *s) int ssl3_send_hello_request(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_HELLO_REQ_A) { - p = (unsigned char *)s->init_buf->data; - *(p++) = SSL3_MT_HELLO_REQUEST; - *(p++) = 0; - *(p++) = 0; - *(p++) = 0; - + ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); s->state = SSL3_ST_SW_HELLO_REQ_B; - /* number of bytes to write */ - s->init_num = 4; - s->init_off = 0; } /* SSL3_ST_SW_HELLO_REQ_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); -} - -int ssl3_check_client_hello(SSL *s) -{ - int ok; - long n; - - /* - * this function is called when we really expect a Certificate message, - * so permit appropriate message length - */ - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_A, - SSL3_ST_SR_CERT_B, - -1, s->max_cert_list, &ok); - if (!ok) - return ((int)n); - s->s3->tmp.reuse_message = 1; - if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) { - /* - * We only allow the client to restart the handshake once per - * negotiation. - */ - if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE) { - SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, - SSL_R_MULTIPLE_SGC_RESTARTS); - return -1; - } - /* - * Throw away what we have done so far in the current handshake, - * which will now be aborted. (A full SSL_clear would be too much.) - */ -#ifndef OPENSSL_NO_DH - if (s->s3->tmp.dh != NULL) { - DH_free(s->s3->tmp.dh); - s->s3->tmp.dh = NULL; - } -#endif -#ifndef OPENSSL_NO_ECDH - if (s->s3->tmp.ecdh != NULL) { - EC_KEY_free(s->s3->tmp.ecdh); - s->s3->tmp.ecdh = NULL; - } -#endif - s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE; - return 2; - } - return 1; + return ssl_do_write(s); } int ssl3_get_client_hello(SSL *s) { - int i, j, ok, al, ret = -1; + int i, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; unsigned int cookie_len; long n; unsigned long id; - unsigned char *p, *d, *q; + unsigned char *p, *d; SSL_CIPHER *c; #ifndef OPENSSL_NO_COMP + unsigned char *q; SSL_COMP *comp = NULL; #endif STACK_OF(SSL_CIPHER) *ciphers = NULL; + if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) + goto retry_cert; + /* * We do this so that we will respond with our native type. If we are * TLSv1 and we get SSLv3, we will respond with TLSv1, This down @@ -1016,8 +955,9 @@ int ssl3_get_client_hello(SSL *s) s->client_version = (((int)p[0]) << 8) | (int)p[1]; p += 2; - if ((s->version == DTLS1_VERSION && s->client_version > s->version) || - (s->version != DTLS1_VERSION && s->client_version < s->version)) { + if (SSL_IS_DTLS(s) ? (s->client_version > s->version && + s->method->version != DTLS_ANY_VERSION) + : (s->client_version < s->version)) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && !s->enc_write_ctx && !s->write_hash) { @@ -1107,7 +1047,7 @@ int ssl3_get_client_hello(SSL *s) p += j; - if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { /* cookie stuff */ if (p + 1 > d + n) { al = SSL_AD_DECODE_ERROR; @@ -1155,11 +1095,36 @@ int ssl3_get_client_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); goto f_err; } - - ret = 2; + /* Set to -2 so if successful we return 2 */ + ret = -2; } p += cookie_len; + if (s->method->version == DTLS_ANY_VERSION) { + /* Select version to use */ + if (s->client_version <= DTLS1_2_VERSION && + !(s->options & SSL_OP_NO_DTLSv1_2)) { + s->version = DTLS1_2_VERSION; + s->method = DTLSv1_2_server_method(); + } else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } else if (s->client_version <= DTLS1_VERSION && + !(s->options & SSL_OP_NO_DTLSv1)) { + s->version = DTLS1_VERSION; + s->method = DTLSv1_server_method(); + } else { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_WRONG_VERSION_NUMBER); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version; + } } if (p + 2 > d + n) { @@ -1248,7 +1213,9 @@ int ssl3_get_client_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); goto f_err; } +#ifndef OPENSSL_NO_COMP q = p; +#endif for (j = 0; j < i; j++) { if (p[j] == 0) break; @@ -1264,16 +1231,11 @@ int ssl3_get_client_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { - /* 'al' set by ssl_parse_clienthello_tlsext */ + if (!ssl_parse_clienthello_tlsext(s, &p, d, n)) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT); - goto f_err; + goto err; } } - if (ssl_check_clienthello_tlsext_early(s) <= 0) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } /* * Check if we want to use external pre-shared secret for this handshake @@ -1285,7 +1247,6 @@ int ssl3_get_client_hello(SSL *s) unsigned char *pos; pos = s->s3->server_random; if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0) { - al = SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -1344,7 +1305,6 @@ int ssl3_get_client_hello(SSL *s) /* Perform sanity checks on resumed compression algorithm */ /* Can't disable compression */ if (s->options & SSL_OP_NO_COMPRESSION) { - al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION); goto f_err; @@ -1358,7 +1318,6 @@ int ssl3_get_client_hello(SSL *s) } } if (s->s3->tmp.new_compression == NULL) { - al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_INVALID_COMPRESSION_ALGORITHM); goto f_err; @@ -1404,7 +1363,6 @@ int ssl3_get_client_hello(SSL *s) * using compression. */ if (s->session->compress_meth != 0) { - al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1429,6 +1387,25 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } ciphers = NULL; + if (!tls1_set_server_sigalgs(s)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } + /* Let cert callback update server certificates if required */ + retry_cert: + if (s->cert->cert_cb) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + return -1; + } + s->rwstate = SSL_NOTHING; + } c = ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); if (c == NULL) { @@ -1464,16 +1441,13 @@ int ssl3_get_client_hello(SSL *s) s->s3->tmp.new_cipher = s->session->cipher; } - if (TLS1_get_version(s) < TLS1_2_VERSION - || !(s->verify_mode & SSL_VERIFY_PEER)) { - if (!ssl3_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; + if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) { + if (!ssl3_digest_cached_records(s)) goto f_err; - } } /*- - * we now have the following setup. + * we now have the following setup. * client_random * cipher_list - our prefered list of ciphers * ciphers - the clients prefered list of ciphers @@ -1493,7 +1467,7 @@ int ssl3_get_client_hello(SSL *s) } if (ret < 0) - ret = 1; + ret = -ret; if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); @@ -1503,7 +1477,7 @@ int ssl3_get_client_hello(SSL *s) if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); - return (ret); + return ret < 0 ? -1 : ret; } int ssl3_send_server_hello(SSL *s) @@ -1511,6 +1485,7 @@ int ssl3_send_server_hello(SSL *s) unsigned char *buf; unsigned char *p, *d; int i, sl; + int al = 0; unsigned long l; if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { @@ -1523,7 +1498,7 @@ int ssl3_send_server_hello(SSL *s) } #endif /* Do the message type and length last */ - d = p = &(buf[4]); + d = p = ssl_handshake_start(s); *(p++) = s->version >> 8; *(p++) = s->version & 0xff; @@ -1582,9 +1557,9 @@ int ssl3_send_server_hello(SSL *s) return -1; } if ((p = - ssl_add_serverhello_tlsext(s, p, - buf + SSL3_RT_MAX_PLAIN_LENGTH)) == - NULL) { + ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH, + &al)) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; return -1; @@ -1592,41 +1567,24 @@ int ssl3_send_server_hello(SSL *s) #endif /* do the header */ l = (p - d); - d = buf; - *(d++) = SSL3_MT_SERVER_HELLO; - l2n3(l, d); - + ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); s->state = SSL3_ST_SW_SRVR_HELLO_B; - /* number of bytes to write */ - s->init_num = p - buf; - s->init_off = 0; } /* SSL3_ST_SW_SRVR_HELLO_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_done(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_SRVR_DONE_A) { - p = (unsigned char *)s->init_buf->data; - - /* do the header */ - *(p++) = SSL3_MT_SERVER_DONE; - *(p++) = 0; - *(p++) = 0; - *(p++) = 0; - + ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); s->state = SSL3_ST_SW_SRVR_DONE_B; - /* number of bytes to write */ - s->init_num = 4; - s->init_off = 0; } /* SSL3_ST_SW_SRVR_DONE_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_key_exchange(SSL *s) @@ -1751,7 +1709,12 @@ int ssl3_send_server_key_exchange(SSL *s) const EC_GROUP *group; ecdhp = cert->ecdh_tmp; - if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) { + if (s->cert->ecdh_tmp_auto) { + /* Get NID of appropriate shared curve */ + int nid = tls1_shared_curve(s, -2); + if (nid != NID_undef) + ecdhp = EC_KEY_new_by_curve_name(nid); + } else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) { ecdhp = s->cert->ecdh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3-> tmp.new_cipher), @@ -1776,7 +1739,9 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { + if (s->cert->ecdh_tmp_auto) + ecdh = ecdhp; + else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } @@ -1920,12 +1885,11 @@ int ssl3_send_server_key_exchange(SSL *s) kn = 0; } - if (!BUF_MEM_grow_clean(buf, n + 4 + kn)) { + if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_BUF); goto err; } - d = (unsigned char *)s->init_buf->data; - p = &(d[4]); + d = p = ssl_handshake_start(s); for (i = 0; i < 4 && r[i] != NULL; i++) { #ifndef OPENSSL_NO_SRP @@ -1980,8 +1944,7 @@ int ssl3_send_server_key_exchange(SSL *s) * points to the space at the end. */ #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA - && TLS1_get_version(s) < TLS1_2_VERSION) { + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { q = md_buf; j = 0; for (num = 2; num > 0; num--) { @@ -1993,7 +1956,7 @@ int ssl3_send_server_key_exchange(SSL *s) SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx, &(d[4]), n); + EVP_DigestUpdate(&md_ctx, d, n); EVP_DigestFinal_ex(&md_ctx, q, (unsigned int *)&i); q += i; j += i; @@ -2008,10 +1971,8 @@ int ssl3_send_server_key_exchange(SSL *s) } else #endif if (md) { - /* - * For TLS1.2 and later send signature algorithm - */ - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + /* send signature algorithm */ + if (SSL_USE_SIGALGS(s)) { if (!tls12_get_sigandhash(p, pkey, md)) { /* Should never happen */ al = SSL_AD_INTERNAL_ERROR; @@ -2029,7 +1990,7 @@ int ssl3_send_server_key_exchange(SSL *s) SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx, &(d[4]), n); + EVP_SignUpdate(&md_ctx, d, n); if (!EVP_SignFinal(&md_ctx, &(p[2]), (unsigned int *)&i, pkey)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_EVP); @@ -2037,7 +1998,7 @@ int ssl3_send_server_key_exchange(SSL *s) } s2n(i, p); n += i + 2; - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) n += 2; } else { /* Is this error check actually needed? */ @@ -2048,19 +2009,12 @@ int ssl3_send_server_key_exchange(SSL *s) } } - *(d++) = SSL3_MT_SERVER_KEY_EXCHANGE; - l2n3(n, d); - - /* - * we should now have things packed up, so lets send it off - */ - s->init_num = n + 4; - s->init_off = 0; + ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); } s->state = SSL3_ST_SW_KEY_EXCH_B; EVP_MD_CTX_cleanup(&md_ctx); - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: @@ -2085,7 +2039,7 @@ int ssl3_send_certificate_request(SSL *s) if (s->state == SSL3_ST_SW_CERT_REQ_A) { buf = s->init_buf; - d = p = (unsigned char *)&(buf->data[4]); + d = p = ssl_handshake_start(s); /* get the list of acceptable cert types */ p++; @@ -2094,10 +2048,12 @@ int ssl3_send_certificate_request(SSL *s) p += n; n++; - if (TLS1_get_version(s) >= TLS1_2_VERSION) { - nl = tls12_get_req_sig_algs(s, p + 2); + if (SSL_USE_SIGALGS(s)) { + const unsigned char *psigs; + nl = tls12_get_psigalgs(s, &psigs); s2n(nl, p); - p += nl + 2; + memcpy(p, psigs, nl); + p += nl; n += nl + 2; } @@ -2111,12 +2067,13 @@ int ssl3_send_certificate_request(SSL *s) for (i = 0; i < sk_X509_NAME_num(sk); i++) { name = sk_X509_NAME_value(sk, i); j = i2d_X509_NAME(name, NULL); - if (!BUF_MEM_grow_clean(buf, 4 + n + j + 2)) { + if (!BUF_MEM_grow_clean + (buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) { SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST, ERR_R_BUF_LIB); goto err; } - p = (unsigned char *)&(buf->data[4 + n]); + p = ssl_handshake_start(s) + n; if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) { s2n(j, p); i2d_X509_NAME(name, &p); @@ -2134,39 +2091,32 @@ int ssl3_send_certificate_request(SSL *s) } } /* else no CA names */ - p = (unsigned char *)&(buf->data[4 + off]); + p = ssl_handshake_start(s) + off; s2n(nl, p); - d = (unsigned char *)buf->data; - *(d++) = SSL3_MT_CERTIFICATE_REQUEST; - l2n3(n, d); + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); - /* - * we should now have things packed up, so lets send it off - */ - - s->init_num = n + 4; - s->init_off = 0; #ifdef NETSCAPE_HANG_BUG - if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) { - SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST, ERR_R_BUF_LIB); - goto err; + if (!SSL_IS_DTLS(s)) { + if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) { + SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST, ERR_R_BUF_LIB); + goto err; + } + p = (unsigned char *)s->init_buf->data + s->init_num; + /* do the header */ + *(p++) = SSL3_MT_SERVER_DONE; + *(p++) = 0; + *(p++) = 0; + *(p++) = 0; + s->init_num += 4; } - p = (unsigned char *)s->init_buf->data + s->init_num; - - /* do the header */ - *(p++) = SSL3_MT_SERVER_DONE; - *(p++) = 0; - *(p++) = 0; - *(p++) = 0; - s->init_num += 4; #endif s->state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: s->state = SSL_ST_ERR; return (-1); @@ -2184,7 +2134,7 @@ int ssl3_get_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_DH BIGNUM *pub = NULL; - DH *dh_srvr; + DH *dh_srvr, *dh_clnt = NULL; #endif #ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err; @@ -2355,8 +2305,20 @@ int ssl3_get_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_DH if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) { - n2s(p, i); - if (n != i + 2) { + int idx = -1; + EVP_PKEY *skey = NULL; + if (n > 1) { + n2s(p, i); + } else { + if (alg_k & SSL_kDHE) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + goto f_err; + } + i = 0; + } + if (n && n != i + 2) { if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); @@ -2366,23 +2328,45 @@ int ssl3_get_client_key_exchange(SSL *s) i = (int)n; } } - - if (n == 0L) { /* the parameters are in the cert */ + if (alg_k & SSL_kDHr) + idx = SSL_PKEY_DH_RSA; + else if (alg_k & SSL_kDHd) + idx = SSL_PKEY_DH_DSA; + if (idx >= 0) { + skey = s->cert->pkeys[idx].privatekey; + if ((skey == NULL) || + (skey->type != EVP_PKEY_DH) || (skey->pkey.dh == NULL)) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + dh_srvr = skey->pkey.dh; + } else if (s->s3->tmp.dh == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_UNABLE_TO_DECODE_DH_CERTS); + SSL_R_MISSING_TMP_DH_KEY); goto f_err; - } else { - if (s->s3->tmp.dh == NULL) { + } else + dh_srvr = s->s3->tmp.dh; + + if (n == 0L) { + /* Get pubkey from cert */ + EVP_PKEY *clkey = X509_get_pubkey(s->session->peer); + if (clkey) { + if (EVP_PKEY_cmp_parameters(clkey, skey) == 1) + dh_clnt = EVP_PKEY_get1_DH(clkey); + } + if (dh_clnt == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_TMP_DH_KEY); goto f_err; - } else - dh_srvr = s->s3->tmp.dh; - } - - pub = BN_bin2bn(p, i, NULL); + } + EVP_PKEY_free(clkey); + pub = dh_clnt->pub_key; + } else + pub = BN_bin2bn(p, i, NULL); if (pub == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_BN_LIB); goto err; @@ -2398,8 +2382,10 @@ int ssl3_get_client_key_exchange(SSL *s) DH_free(s->s3->tmp.dh); s->s3->tmp.dh = NULL; - - BN_clear_free(pub); + if (dh_clnt) + DH_free(dh_clnt); + else + BN_clear_free(pub); pub = NULL; s->session->master_key_length = s->method->ssl3_enc->generate_master_secret(s, @@ -2407,6 +2393,8 @@ int ssl3_get_client_key_exchange(SSL *s) session->master_key, p, i); OPENSSL_cleanse(p, i); + if (dh_clnt) + return 2; } else #endif #ifndef OPENSSL_NO_KRB5 @@ -3007,24 +2995,12 @@ int ssl3_get_cert_verify(SSL *s) pkey->type == NID_id_GostR3410_2001)) { i = 64; } else { - if (TLS1_get_version(s) >= TLS1_2_VERSION) { - int sigalg = tls12_get_sigid(pkey); - /* Should never happen */ - if (sigalg == -1) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR); + if (SSL_USE_SIGALGS(s)) { + int rv = tls12_check_peer_sigalg(&md, s, p, pkey); + if (rv == -1) { al = SSL_AD_INTERNAL_ERROR; goto f_err; - } - /* Check key type is consistent with signature */ - if (sigalg != (int)p[1]) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, - SSL_R_WRONG_SIGNATURE_TYPE); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - md = tls12_get_hash(p[0]); - if (md == NULL) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_UNKNOWN_DIGEST); + } else if (rv == 0) { al = SSL_AD_DECODE_ERROR; goto f_err; } @@ -3049,7 +3025,7 @@ int ssl3_get_cert_verify(SSL *s) goto f_err; } - if (TLS1_get_version(s) >= TLS1_2_VERSION) { + if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); @@ -3272,7 +3248,7 @@ int ssl3_get_client_certificate(SSL *s) if (i <= 0) { al = ssl_verify_alarm_type(s->verify_result); SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, - SSL_R_NO_CERTIFICATE_RETURNED); + SSL_R_CERTIFICATE_VERIFY_FAILED); goto f_err; } } @@ -3320,12 +3296,11 @@ int ssl3_get_client_certificate(SSL *s) int ssl3_send_server_certificate(SSL *s) { - unsigned long l; - X509 *x; + CERT_PKEY *cpk; if (s->state == SSL3_ST_SW_CERT_A) { - x = ssl_get_server_send_cert(s); - if (x == NULL) { + cpk = ssl_get_server_send_pkey(s); + if (cpk == NULL) { /* VRS: allow null cert if auth == KRB5 */ if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5)) { @@ -3336,19 +3311,16 @@ int ssl3_send_server_certificate(SSL *s) } } - l = ssl3_output_cert_chain(s, x); - if (!l) { + if (!ssl3_output_cert_chain(s, cpk)) { SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; return (0); } s->state = SSL3_ST_SW_CERT_B; - s->init_num = (int)l; - s->init_off = 0; } /* SSL3_ST_SW_CERT_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #ifndef OPENSSL_NO_TLSEXT @@ -3415,22 +3387,18 @@ int ssl3_send_newsession_ticket(SSL *s) /*- * Grow buffer if need be: the length calculation is as - * follows 1 (size of message name) + 3 (message length - * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) + + * follows handshake_header_length + + * 4 (ticket lifetime hint) + 2 (ticket length) + * 16 (key name) + max_iv_len (iv length) + * session_length + max_enc_block_size (max encrypted session * length) + max_md_size (HMAC). */ if (!BUF_MEM_grow(s->init_buf, - 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + - EVP_MAX_MD_SIZE + slen)) + SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH + + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) goto err; - p = (unsigned char *)s->init_buf->data; - /* do the header */ - *(p++) = SSL3_MT_NEWSESSION_TICKET; - /* Skip message length for now */ - p += 3; + p = ssl_handshake_start(s); /* * Initialize HMAC and cipher contexts. If callback present it does * all the work otherwise use generated values from parent ctx. @@ -3486,21 +3454,17 @@ int ssl3_send_newsession_ticket(SSL *s) p += hlen; /* Now write out lengths: p points to end of data written */ /* Total length */ - len = p - (unsigned char *)s->init_buf->data; - p = (unsigned char *)s->init_buf->data + 1; - l2n3(len - 4, p); /* Message length */ - p += 4; - s2n(len - 10, p); /* Ticket length */ - - /* number of bytes to write */ - s->init_num = len; + len = p - ssl_handshake_start(s); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(s) + 4; + s2n(len - 6, p); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); s->state = SSL3_ST_SW_SESSION_TICKET_B; - s->init_off = 0; OPENSSL_free(senc); } /* SSL3_ST_SW_SESSION_TICKET_B */ - return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: if (senc) OPENSSL_free(senc); @@ -3627,4 +3591,5 @@ int ssl3_get_next_proto(SSL *s) return 1; } # endif + #endif diff --git a/ssl/srtp.h b/ssl/srtp.h index 10082c939abb..2279c32b895a 100644 --- a/ssl/srtp.h +++ b/ssl/srtp.h @@ -134,7 +134,6 @@ extern "C" { int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles); -SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); diff --git a/ssl/ssl.h b/ssl/ssl.h index d2ab0c074c99..6fe1a2474d43 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -242,22 +242,24 @@ extern "C" { # define SSL_TXT_NULL "NULL" # define SSL_TXT_kRSA "kRSA" -# define SSL_TXT_kDHr "kDHr"/* no such ciphersuites supported! */ -# define SSL_TXT_kDHd "kDHd"/* no such ciphersuites supported! */ -# define SSL_TXT_kDH "kDH"/* no such ciphersuites supported! */ +# define SSL_TXT_kDHr "kDHr" +# define SSL_TXT_kDHd "kDHd" +# define SSL_TXT_kDH "kDH" # define SSL_TXT_kEDH "kEDH" +# define SSL_TXT_kDHE "kDHE"/* alias for kEDH */ # define SSL_TXT_kKRB5 "kKRB5" # define SSL_TXT_kECDHr "kECDHr" # define SSL_TXT_kECDHe "kECDHe" # define SSL_TXT_kECDH "kECDH" # define SSL_TXT_kEECDH "kEECDH" +# define SSL_TXT_kECDHE "kECDHE"/* alias for kEECDH */ # define SSL_TXT_kPSK "kPSK" # define SSL_TXT_kGOST "kGOST" # define SSL_TXT_kSRP "kSRP" # define SSL_TXT_aRSA "aRSA" # define SSL_TXT_aDSS "aDSS" -# define SSL_TXT_aDH "aDH"/* no such ciphersuites supported! */ +# define SSL_TXT_aDH "aDH" # define SSL_TXT_aECDH "aECDH" # define SSL_TXT_aKRB5 "aKRB5" # define SSL_TXT_aECDSA "aECDSA" @@ -270,10 +272,12 @@ extern "C" { # define SSL_TXT_DSS "DSS" # define SSL_TXT_DH "DH" # define SSL_TXT_EDH "EDH"/* same as "kEDH:-ADH" */ +# define SSL_TXT_DHE "DHE"/* alias for EDH */ # define SSL_TXT_ADH "ADH" # define SSL_TXT_RSA "RSA" # define SSL_TXT_ECDH "ECDH" # define SSL_TXT_EECDH "EECDH"/* same as "kEECDH:-AECDH" */ +# define SSL_TXT_ECDHE "ECDHE"/* alias for ECDHE" */ # define SSL_TXT_AECDH "AECDH" # define SSL_TXT_ECDSA "ECDSA" # define SSL_TXT_KRB5 "KRB5" @@ -370,6 +374,8 @@ typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; typedef struct ssl_method_st SSL_METHOD; typedef struct ssl_cipher_st SSL_CIPHER; typedef struct ssl_session_st SSL_SESSION; +typedef struct tls_sigalgs_st TLS_SIGALGS; +typedef struct ssl_conf_ctx_st SSL_CONF_CTX; DECLARE_STACK_OF(SSL_CIPHER) @@ -389,6 +395,23 @@ typedef int (*tls_session_secret_cb_fn) (SSL *s, void *secret, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); +# ifndef OPENSSL_NO_TLSEXT + +/* Typedefs for handling custom extensions */ + +typedef int (*custom_ext_add_cb) (SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *add_arg); + +typedef void (*custom_ext_free_cb) (SSL *s, unsigned int ext_type, + const unsigned char *out, void *add_arg); + +typedef int (*custom_ext_parse_cb) (SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *parse_arg); + +# endif + # ifndef OPENSSL_NO_SSL_INTERN /* used to hold info on the particular ciphers used */ @@ -624,6 +647,12 @@ struct ssl_session_st { # define SSL_OP_NO_TLSv1_2 0x08000000L # define SSL_OP_NO_TLSv1_1 0x10000000L +# define SSL_OP_NO_DTLSv1 0x04000000L +# define SSL_OP_NO_DTLSv1_2 0x08000000L + +# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\ + SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2) + /* * These next two were never actually used for anything since SSLeay zap so * we have some more flags. @@ -685,6 +714,69 @@ struct ssl_session_st { */ # define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L +/* Cert related flags */ +/* + * Many implementations ignore some aspects of the TLS standards such as + * enforcing certifcate chain algorithms. When this is set we enforce them. + */ +# define SSL_CERT_FLAG_TLS_STRICT 0x00000001L + +/* Suite B modes, takes same values as certificate verify flags */ +# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000 + +/* Perform all sorts of protocol violations for testing purposes */ +# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000 + +/* Flags for building certificate chains */ +/* Treat any existing certificates as untrusted CAs */ +# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1 +/* Don't include root CA in chain */ +# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2 +/* Just check certificates already there */ +# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4 +/* Ignore verification errors */ +# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8 +/* Clear verification errors from queue */ +# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10 + +/* Flags returned by SSL_check_chain */ +/* Certificate can be used with this session */ +# define CERT_PKEY_VALID 0x1 +/* Certificate can also be used for signing */ +# define CERT_PKEY_SIGN 0x2 +/* EE certificate signing algorithm OK */ +# define CERT_PKEY_EE_SIGNATURE 0x10 +/* CA signature algorithms OK */ +# define CERT_PKEY_CA_SIGNATURE 0x20 +/* EE certificate parameters OK */ +# define CERT_PKEY_EE_PARAM 0x40 +/* CA certificate parameters OK */ +# define CERT_PKEY_CA_PARAM 0x80 +/* Signing explicitly allowed as opposed to SHA1 fallback */ +# define CERT_PKEY_EXPLICIT_SIGN 0x100 +/* Client CA issuer names match (always set for server cert) */ +# define CERT_PKEY_ISSUER_NAME 0x200 +/* Cert type matches client types (always set for server cert) */ +# define CERT_PKEY_CERT_TYPE 0x400 +/* Cert chain suitable to Suite B */ +# define CERT_PKEY_SUITEB 0x800 + +# define SSL_CONF_FLAG_CMDLINE 0x1 +# define SSL_CONF_FLAG_FILE 0x2 +# define SSL_CONF_FLAG_CLIENT 0x4 +# define SSL_CONF_FLAG_SERVER 0x8 +# define SSL_CONF_FLAG_SHOW_ERRORS 0x10 +# define SSL_CONF_FLAG_CERTIFICATE 0x20 +/* Configuration value types */ +# define SSL_CONF_TYPE_UNKNOWN 0x0 +# define SSL_CONF_TYPE_STRING 0x1 +# define SSL_CONF_TYPE_FILE 0x2 +# define SSL_CONF_TYPE_DIR 0x3 + /* * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they * cannot be used to clear bits. @@ -730,6 +822,15 @@ struct ssl_session_st { SSL_ctrl((ssl),SSL_CTRL_TLS_EXT_SEND_HEARTBEAT,0,NULL) # endif +# define SSL_CTX_set_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_set_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_CTX_clear_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) +# define SSL_clear_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) + void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb) (int write_p, int version, int content_type, const void *buf, @@ -1042,6 +1143,43 @@ struct ssl_ctx_st { # endif /* SRTP profiles we are willing to do from RFC 5764 */ STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /*- + * For a server, this contains a callback function that allows the + * server to select the protocol for the connection. + * out: on successful return, this must point to the raw protocol + * name (without the length prefix). + * outlen: on successful return, this contains the length of |*out|. + * in: points to the client's list of supported protocols in + * wire-format. + * inlen: the length of |in|. + */ + int (*alpn_select_cb) (SSL *s, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg); + void *alpn_select_cb_arg; + + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn_client_proto_list; + unsigned alpn_client_proto_list_len; + +# ifndef OPENSSL_NO_EC + /* EC extension values inherited by SSL structure */ + size_t tlsext_ecpointformatlist_length; + unsigned char *tlsext_ecpointformatlist; + size_t tlsext_ellipticcurvelist_length; + unsigned char *tlsext_ellipticcurvelist; +# endif /* OPENSSL_NO_EC */ # endif }; @@ -1144,19 +1282,35 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, const unsigned char *in, unsigned int inlen, void *arg), void *arg); +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned *len); +# endif +# ifndef OPENSSL_NO_TLSEXT int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, const unsigned char *client, unsigned int client_len); -void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, - unsigned *len); - -# define OPENSSL_NPN_UNSUPPORTED 0 -# define OPENSSL_NPN_NEGOTIATED 1 -# define OPENSSL_NPN_NO_OVERLAP 2 # endif +# define OPENSSL_NPN_UNSUPPORTED 0 +# define OPENSSL_NPN_NEGOTIATED 1 +# define OPENSSL_NPN_NO_OVERLAP 2 + +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned protos_len); +int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned protos_len); +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len); + # ifndef OPENSSL_NO_PSK /* * the maximum length of the buffer given to callbacks containing the @@ -1228,6 +1382,27 @@ const char *SSL_get_psk_identity_hint(const SSL *s); const char *SSL_get_psk_identity(const SSL *s); # endif +# ifndef OPENSSL_NO_TLSEXT +/* Register callbacks to handle custom TLS Extensions for client or server. */ + +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +int SSL_extension_supported(unsigned int ext_type); + +# endif + # define SSL_NOTHING 1 # define SSL_WRITING 2 # define SSL_READING 3 @@ -1502,6 +1677,14 @@ struct ssl_st { /* ctx for SRP authentication */ SRP_CTX srp_ctx; # endif +# ifndef OPENSSL_NO_TLSEXT + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn_client_proto_list; + unsigned alpn_client_proto_list_len; +# endif /* OPENSSL_NO_TLSEXT */ }; # endif @@ -1758,7 +1941,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING 86 # define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS 87 # endif -# endif +# endif /* OPENSSL_NO_TLSEXT */ # define DTLS_CTRL_GET_TIMEOUT 73 # define DTLS_CTRL_HANDLE_TIMEOUT 74 # define DTLS_CTRL_LISTEN 75 @@ -1767,9 +1950,37 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_CTRL_CLEAR_MODE 78 # define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 # define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 +# define SSL_CTRL_CHAIN 88 +# define SSL_CTRL_CHAIN_CERT 89 +# define SSL_CTRL_GET_CURVES 90 +# define SSL_CTRL_SET_CURVES 91 +# define SSL_CTRL_SET_CURVES_LIST 92 +# define SSL_CTRL_GET_SHARED_CURVE 93 +# define SSL_CTRL_SET_ECDH_AUTO 94 +# define SSL_CTRL_SET_SIGALGS 97 +# define SSL_CTRL_SET_SIGALGS_LIST 98 +# define SSL_CTRL_CERT_FLAGS 99 +# define SSL_CTRL_CLEAR_CERT_FLAGS 100 +# define SSL_CTRL_SET_CLIENT_SIGALGS 101 +# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102 +# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103 +# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104 +# define SSL_CTRL_BUILD_CERT_CHAIN 105 +# define SSL_CTRL_SET_VERIFY_CERT_STORE 106 +# define SSL_CTRL_SET_CHAIN_CERT_STORE 107 +# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108 +# define SSL_CTRL_GET_SERVER_TMP_KEY 109 +# define SSL_CTRL_GET_RAW_CIPHERLIST 110 +# define SSL_CTRL_GET_EC_POINT_FORMATS 111 +# define SSL_CTRL_GET_CHAIN_CERTS 115 +# define SSL_CTRL_SELECT_CURRENT_CERT 116 +# define SSL_CTRL_SET_CURRENT_CERT 117 # define SSL_CTRL_CHECK_PROTO_VERSION 119 # define DTLS_CTRL_SET_LINK_MTU 120 # define DTLS_CTRL_GET_LINK_MIN_MTU 121 +# define SSL_CERT_SET_FIRST 1 +# define SSL_CERT_SET_NEXT 2 +# define SSL_CERT_SET_SERVER 3 # define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) # define DTLSv1_handle_timeout(ssl) \ @@ -1804,8 +2015,108 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) # define SSL_CTX_get_extra_chain_certs(ctx,px509) \ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509) +# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509) # define SSL_CTX_clear_extra_chain_certs(ctx) \ SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL) +# define SSL_CTX_set0_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk) +# define SSL_CTX_set1_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)sk) +# define SSL_CTX_add0_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) +# define SSL_CTX_add1_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) +# define SSL_CTX_get0_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_CTX_clear_chain_certs(ctx) \ + SSL_CTX_set0_chain(ctx,NULL) +# define SSL_CTX_build_cert_chain(ctx, flags) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_CTX_select_current_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509) +# define SSL_CTX_set_current_cert(ctx, op) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_CTX_set0_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) +# define SSL_CTX_set1_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st) +# define SSL_CTX_set0_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st) +# define SSL_CTX_set1_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st) +# define SSL_set0_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk) +# define SSL_set1_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)sk) +# define SSL_add0_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) +# define SSL_add1_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) +# define SSL_get0_chain_certs(ctx,px509) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_clear_chain_certs(ctx) \ + SSL_set0_chain(ctx,NULL) +# define SSL_build_cert_chain(s, flags) \ + SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_select_current_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509) +# define SSL_set_current_cert(ctx,op) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_set0_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) +# define SSL_set1_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st) +# define SSL_set0_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st) +# define SSL_set1_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st) +# define SSL_get1_curves(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CURVES,0,(char *)s) +# define SSL_CTX_set1_curves(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist) +# define SSL_CTX_set1_curves_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s) +# define SSL_set1_curves(ctx, clist, clistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist) +# define SSL_set1_curves_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s) +# define SSL_get_shared_curve(s, n) \ + SSL_ctrl(s,SSL_CTRL_GET_SHARED_CURVE,n,NULL) +# define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) +# define SSL_set_ecdh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) +# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)slist) +# define SSL_CTX_set1_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) +# define SSL_set1_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,clistlen,(int *)slist) +# define SSL_set1_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) +# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)slist) +# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)s) +# define SSL_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,clistlen,(int *)slist) +# define SSL_set1_client_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)s) +# define SSL_get0_certificate_types(s, clist) \ + SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)clist) +# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)clist) +# define SSL_set1_client_certificate_types(s, clist, clistlen) \ + SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)clist) +# define SSL_get_peer_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn) +# define SSL_get_server_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_SERVER_TMP_KEY,0,pk) +# define SSL_get0_raw_cipherlist(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,(char *)plst) +# define SSL_get0_ec_point_formats(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,(char *)plst) # ifndef OPENSSL_NO_BIO BIO_METHOD *BIO_f_ssl(void); BIO *BIO_new_ssl(SSL_CTX *ctx, int client); @@ -1859,6 +2170,7 @@ int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *); void SSL_set_verify(SSL *s, int mode, int (*callback) (int ok, X509_STORE_CTX *ctx)); void SSL_set_verify_depth(SSL *s, int depth); +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg); # ifndef OPENSSL_NO_RSA int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); # endif @@ -1869,6 +2181,16 @@ int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, int SSL_use_certificate(SSL *ssl, X509 *x); int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); +# ifndef OPENSSL_NO_TLSEXT +/* Set serverinfo data for the current active cert. */ +int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length); +# ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); +# endif /* NO_STDIO */ + +# endif + # ifndef OPENSSL_NO_STDIO int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); @@ -1943,6 +2265,8 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb) (X509_STORE_CTX *, void *), void *arg); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), + void *arg); # ifndef OPENSSL_NO_RSA int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); # endif @@ -1976,6 +2300,9 @@ int SSL_set_trust(SSL *s, int trust); int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + # ifndef OPENSSL_NO_SRP int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name); int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password); @@ -2000,6 +2327,7 @@ char *SSL_get_srp_username(SSL *s); char *SSL_get_srp_userinfo(SSL *s); # endif +void SSL_certs_clear(SSL *s); void SSL_free(SSL *ssl); int SSL_accept(SSL *ssl); int SSL_connect(SSL *ssl); @@ -2052,6 +2380,14 @@ const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */ const SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */ const SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_2_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_server_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_client_method(void); /* DTLSv1.2 */ + +const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */ +const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */ +const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */ + STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); int SSL_do_handshake(SSL *s); @@ -2060,6 +2396,7 @@ int SSL_renegotiate_abbreviated(SSL *s); int SSL_renegotiate_pending(SSL *s); int SSL_shutdown(SSL *s); +const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx); const SSL_METHOD *SSL_get_ssl_method(SSL *s); int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); const char *SSL_alert_type_string_long(int value); @@ -2089,7 +2426,10 @@ SSL *SSL_dup(SSL *ssl); X509 *SSL_get_certificate(const SSL *ssl); /* * EVP_PKEY - */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl); + */ struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl); + +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); @@ -2197,6 +2537,9 @@ const COMP_METHOD *SSL_get_current_compression(SSL *s); const COMP_METHOD *SSL_get_current_expansion(SSL *s); const char *SSL_COMP_get_name(const COMP_METHOD *comp); STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths); +void SSL_COMP_free_compression_methods(void); int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); # else const void *SSL_get_current_compression(SSL *s); @@ -2206,6 +2549,8 @@ void *SSL_COMP_get_compression_methods(void); int SSL_COMP_add_compression_method(int id, void *cm); # endif +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr); + /* TLS extensions functions */ int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); @@ -2219,6 +2564,27 @@ int SSL_set_session_secret_cb(SSL *s, void SSL_set_debug(SSL *s, int debug); int SSL_cache_hit(SSL *s); +int SSL_is_server(SSL *s); + +SSL_CONF_CTX *SSL_CONF_CTX_new(void); +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx); +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx); +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags); +unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags); +int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre); + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl); +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx); + +int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value); +int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv); +int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd); + +# ifndef OPENSSL_NO_SSL_TRACE +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); +const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c); +# endif # ifndef OPENSSL_NO_UNIT_TEST const struct openssl_ssl_test_functions *SSL_test_functions(void); @@ -2234,6 +2600,7 @@ void ERR_load_SSL_strings(void); /* Error codes for the SSL functions. */ /* Function codes. */ +# define SSL_F_CHECK_SUITEB_CIPHER_LIST 331 # define SSL_F_CLIENT_CERTIFICATE 100 # define SSL_F_CLIENT_FINISHED 167 # define SSL_F_CLIENT_HELLO 101 @@ -2274,6 +2641,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_GET_CLIENT_MASTER_KEY 107 # define SSL_F_GET_SERVER_FINISHED 108 # define SSL_F_GET_SERVER_HELLO 109 +# define SSL_F_GET_SERVER_STATIC_DH_KEY 340 # define SSL_F_GET_SERVER_VERIFY 110 # define SSL_F_I2D_SSL_SESSION 111 # define SSL_F_READ_N 112 @@ -2346,6 +2714,8 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 # define SSL_F_SSL3_WRITE_BYTES 158 # define SSL_F_SSL3_WRITE_PENDING 159 +# define SSL_F_SSL_ADD_CERT_CHAIN 318 +# define SSL_F_SSL_ADD_CERT_TO_BUF 319 # define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 # define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 # define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 @@ -2355,6 +2725,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278 # define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308 # define SSL_F_SSL_BAD_METHOD 160 +# define SSL_F_SSL_BUILD_CERT_CHAIN 332 # define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 # define SSL_F_SSL_CERT_DUP 221 # define SSL_F_SSL_CERT_INST 222 @@ -2367,6 +2738,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 # define SSL_F_SSL_CLEAR 164 # define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +# define SSL_F_SSL_CONF_CMD 334 # define SSL_F_SSL_CREATE_CIPHER_LIST 166 # define SSL_F_SSL_CTRL 232 # define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 @@ -2389,9 +2761,12 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +# define SSL_F_SSL_CTX_USE_SERVERINFO 336 +# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 337 # define SSL_F_SSL_DO_HANDSHAKE 180 # define SSL_F_SSL_GET_NEW_SESSION 181 # define SSL_F_SSL_GET_PREV_SESSION 217 +# define SSL_F_SSL_GET_SERVER_CERT_INDEX 322 # define SSL_F_SSL_GET_SERVER_SEND_CERT 182 # define SSL_F_SSL_GET_SERVER_SEND_PKEY 317 # define SSL_F_SSL_GET_SIGN_PKEY 183 @@ -2410,6 +2785,8 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL_READ 223 # define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 # define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320 +# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321 # define SSL_F_SSL_SESSION_DUP 348 # define SSL_F_SSL_SESSION_NEW 189 # define SSL_F_SSL_SESSION_PRINT_FP 190 @@ -2443,16 +2820,19 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 # define SSL_F_SSL_VERIFY_CERT_CHAIN 207 # define SSL_F_SSL_WRITE 208 +# define SSL_F_TLS12_CHECK_PEER_SIGALG 333 # define SSL_F_TLS1_CERT_VERIFY_MAC 286 # define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 # define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274 # define SSL_F_TLS1_ENC 210 # define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 +# define SSL_F_TLS1_GET_CURVELIST 338 # define SSL_F_TLS1_HEARTBEAT 315 # define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT 275 # define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT 276 # define SSL_F_TLS1_PRF 284 # define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +# define SSL_F_TLS1_SET_SERVER_SIGALGS 335 # define SSL_F_WRITE_PENDING 212 /* Reason codes. */ @@ -2462,6 +2842,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_BAD_AUTHENTICATION_TYPE 102 # define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 # define SSL_R_BAD_CHECKSUM 104 +# define SSL_R_BAD_DATA 390 # define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 # define SSL_R_BAD_DECOMPRESSION 107 # define SSL_R_BAD_DH_G_LENGTH 108 @@ -2499,6 +2880,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_BAD_SSL_FILETYPE 124 # define SSL_R_BAD_SSL_SESSION_ID_LENGTH 125 # define SSL_R_BAD_STATE 126 +# define SSL_R_BAD_VALUE 384 # define SSL_R_BAD_WRITE_RETRY 127 # define SSL_R_BIO_NOT_SET 128 # define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129 @@ -2507,6 +2889,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_CA_DN_TOO_LONG 132 # define SSL_R_CCS_RECEIVED_EARLY 133 # define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +# define SSL_R_CERT_CB_ERROR 377 # define SSL_R_CERT_LENGTH_MISMATCH 135 # define SSL_R_CHALLENGE_IS_DIFFERENT 136 # define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 @@ -2534,6 +2917,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 # define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE 322 # define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE 323 +# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374 # define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 310 # define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 # define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 @@ -2547,12 +2931,15 @@ void ERR_load_SSL_strings(void); # define SSL_R_HTTPS_PROXY_REQUEST 155 # define SSL_R_HTTP_REQUEST 156 # define SSL_R_ILLEGAL_PADDING 283 +# define SSL_R_ILLEGAL_SUITEB_DIGEST 380 # define SSL_R_INAPPROPRIATE_FALLBACK 373 # define SSL_R_INCONSISTENT_COMPRESSION 340 # define SSL_R_INVALID_CHALLENGE_LENGTH 158 # define SSL_R_INVALID_COMMAND 280 # define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +# define SSL_R_INVALID_NULL_CMD_NAME 385 # define SSL_R_INVALID_PURPOSE 278 +# define SSL_R_INVALID_SERVERINFO_DATA 388 # define SSL_R_INVALID_SRP_USERNAME 357 # define SSL_R_INVALID_STATUS_RESPONSE 328 # define SSL_R_INVALID_TICKET_KEYS_LENGTH 325 @@ -2578,6 +2965,8 @@ void ERR_load_SSL_strings(void); # define SSL_R_MISSING_DH_KEY 163 # define SSL_R_MISSING_DH_RSA_CERT 164 # define SSL_R_MISSING_DSA_SIGNING_CERT 165 +# define SSL_R_MISSING_ECDH_CERT 382 +# define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 # define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166 # define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167 # define SSL_R_MISSING_RSA_CERTIFICATE 168 @@ -2606,6 +2995,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_NO_COMPRESSION_SPECIFIED 187 # define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330 # define SSL_R_NO_METHOD_SPECIFIED 188 +# define SSL_R_NO_PEM_EXTENSIONS 389 # define SSL_R_NO_PRIVATEKEY 189 # define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 # define SSL_R_NO_PROTOCOLS_AVAILABLE 191 @@ -2613,12 +3003,15 @@ void ERR_load_SSL_strings(void); # define SSL_R_NO_RENEGOTIATION 339 # define SSL_R_NO_REQUIRED_DIGEST 324 # define SSL_R_NO_SHARED_CIPHER 193 +# define SSL_R_NO_SHARED_SIGATURE_ALGORITHMS 376 # define SSL_R_NO_SRTP_PROFILES 359 # define SSL_R_NO_VERIFY_CALLBACK 194 # define SSL_R_NULL_SSL_CTX 195 # define SSL_R_NULL_SSL_METHOD_PASSED 196 # define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 # define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +# define SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE 387 +# define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE 379 # define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297 # define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG 327 # define SSL_R_PACKET_LENGTH_TOO_LONG 198 @@ -2630,6 +3023,8 @@ void ERR_load_SSL_strings(void); # define SSL_R_PEER_ERROR_NO_CERTIFICATE 202 # define SSL_R_PEER_ERROR_NO_CIPHER 203 # define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204 +# define SSL_R_PEM_NAME_BAD_PREFIX 391 +# define SSL_R_PEM_NAME_TOO_SHORT 392 # define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205 # define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206 # define SSL_R_PROTOCOL_IS_SHUTDOWN 207 @@ -2732,6 +3127,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 # define SSL_R_UNKNOWN_CIPHER_RETURNED 248 # define SSL_R_UNKNOWN_CIPHER_TYPE 249 +# define SSL_R_UNKNOWN_CMD_NAME 386 # define SSL_R_UNKNOWN_DIGEST 368 # define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 # define SSL_R_UNKNOWN_PKEY_TYPE 251 @@ -2749,7 +3145,9 @@ void ERR_load_SSL_strings(void); # define SSL_R_UNSUPPORTED_STATUS_TYPE 329 # define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 # define SSL_R_WRITE_BIO_NOT_SET 260 +# define SSL_R_WRONG_CERTIFICATE_TYPE 383 # define SSL_R_WRONG_CIPHER_RETURNED 261 +# define SSL_R_WRONG_CURVE 378 # define SSL_R_WRONG_MESSAGE_TYPE 262 # define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263 # define SSL_R_WRONG_SIGNATURE_LENGTH 264 diff --git a/ssl/ssl3.h b/ssl/ssl3.h index 2dd54626588a..e681d50a9e86 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -159,11 +159,17 @@ extern "C" { # define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 # define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +# define SSL3_CK_DHE_DSS_DES_40_CBC_SHA SSL3_CK_EDH_DSS_DES_40_CBC_SHA # define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +# define SSL3_CK_DHE_DSS_DES_64_CBC_SHA SSL3_CK_EDH_DSS_DES_64_CBC_SHA # define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +# define SSL3_CK_DHE_DSS_DES_192_CBC3_SHA SSL3_CK_EDH_DSS_DES_192_CBC3_SHA # define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +# define SSL3_CK_DHE_RSA_DES_40_CBC_SHA SSL3_CK_EDH_RSA_DES_40_CBC_SHA # define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +# define SSL3_CK_DHE_RSA_DES_64_CBC_SHA SSL3_CK_EDH_RSA_DES_64_CBC_SHA # define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 +# define SSL3_CK_DHE_RSA_DES_192_CBC3_SHA SSL3_CK_EDH_RSA_DES_192_CBC3_SHA # define SSL3_CK_ADH_RC4_40_MD5 0x03000017 # define SSL3_CK_ADH_RC4_128_MD5 0x03000018 @@ -220,6 +226,18 @@ extern "C" { # define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" # define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" +# define SSL3_TXT_DHE_DSS_DES_40_CBC_SHA "EXP-DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_64_CBC_SHA "DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA "DHE-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DHE_RSA_DES_40_CBC_SHA "EXP-DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_64_CBC_SHA "DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA "DHE-RSA-DES-CBC3-SHA" + +/* + * This next block of six "EDH" labels is for backward compatibility with + * older versions of OpenSSL. New code should use the six "DHE" labels above + * instead: + */ # define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" # define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" # define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" @@ -263,6 +281,8 @@ extern "C" { # define SSL3_SESSION_ID_SIZE 32 # define SSL3_RT_HEADER_LENGTH 5 +# define SSL3_HM_HEADER_LENGTH 4 + # ifndef SSL3_ALIGN_PAYLOAD /* * Some will argue that this increases memory footprint, but it's not @@ -342,6 +362,23 @@ extern "C" { # define SSL3_RT_APPLICATION_DATA 23 # define TLS1_RT_HEARTBEAT 24 +/* Pseudo content types to indicate additional parameters */ +# define TLS1_RT_CRYPTO 0x1000 +# define TLS1_RT_CRYPTO_PREMASTER (TLS1_RT_CRYPTO | 0x1) +# define TLS1_RT_CRYPTO_CLIENT_RANDOM (TLS1_RT_CRYPTO | 0x2) +# define TLS1_RT_CRYPTO_SERVER_RANDOM (TLS1_RT_CRYPTO | 0x3) +# define TLS1_RT_CRYPTO_MASTER (TLS1_RT_CRYPTO | 0x4) + +# define TLS1_RT_CRYPTO_READ 0x0000 +# define TLS1_RT_CRYPTO_WRITE 0x0100 +# define TLS1_RT_CRYPTO_MAC (TLS1_RT_CRYPTO | 0x5) +# define TLS1_RT_CRYPTO_KEY (TLS1_RT_CRYPTO | 0x6) +# define TLS1_RT_CRYPTO_IV (TLS1_RT_CRYPTO | 0x7) +# define TLS1_RT_CRYPTO_FIXED_IV (TLS1_RT_CRYPTO | 0x8) + +/* Pseudo content type for SSL/TLS header info */ +# define SSL3_RT_HEADER 0x100 + # define SSL3_AL_WARNING 1 # define SSL3_AL_FATAL 2 @@ -436,14 +473,7 @@ typedef struct ssl3_buffer_st { */ # define SSL3_FLAGS_CCS_OK 0x0080 -/* - * SSL3_FLAGS_SGC_RESTART_DONE is set when we restart a handshake because of - * MS SGC and so prevents us from restarting the handshake in a loop. It's - * reset on a renegotiation, so effectively limits the client to one restart - * per negotiation. This limits the possibility of a DDoS attack where the - * client handshakes in a loop using SGC to restart. Servers which permit - * renegotiation can still be effected, but we can't prevent that. - */ +/* SSL3_FLAGS_SGC_RESTART_DONE is no longer used */ # define SSL3_FLAGS_SGC_RESTART_DONE 0x0040 # ifndef OPENSSL_NO_SSL_INTERN @@ -584,7 +614,20 @@ typedef struct ssl3_state_st { */ char is_probably_safari; # endif /* !OPENSSL_NO_EC */ -# endif /* !OPENSSL_NO_TLSEXT */ + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /* + * In a server these point to the selected ALPN protocol after the + * ClientHello has been processed. In a client these contain the protocol + * that the server selected once the ServerHello has been processed. + */ + unsigned char *alpn_selected; + unsigned alpn_selected_len; +# endif /* OPENSSL_NO_TLSEXT */ } SSL3_STATE; # endif @@ -654,6 +697,7 @@ typedef struct ssl3_state_st { # define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT) # define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT) # define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CLNT_HELLO_D (0x115|SSL_ST_ACCEPT) /* write to client */ # define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT) # define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT) diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index 151422ae7742..e6f515ff62c0 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c @@ -95,6 +95,10 @@ int SSL_library_init(void) EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); # endif +# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA256) + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256()); +# endif #endif #ifndef OPENSSL_NO_CAMELLIA diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 5df2413f7190..93a1eb941ab9 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -139,29 +139,50 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void) static volatile int ssl_x509_store_ctx_idx = -1; int got_write_lock = 0; - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + if (((size_t)&ssl_x509_store_ctx_idx & + (sizeof(ssl_x509_store_ctx_idx) - 1)) + == 0) { /* check alignment, practically always true */ + int ret; + + if ((ret = ssl_x509_store_ctx_idx) < 0) { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if ((ret = ssl_x509_store_ctx_idx) < 0) { + ret = ssl_x509_store_ctx_idx = + X509_STORE_CTX_get_ex_new_index(0, + "SSL for verify callback", + NULL, NULL, NULL); + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } + + return ret; + } else { /* commonly eliminated */ - if (ssl_x509_store_ctx_idx < 0) { - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - got_write_lock = 1; + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); if (ssl_x509_store_ctx_idx < 0) { - ssl_x509_store_ctx_idx = - X509_STORE_CTX_get_ex_new_index(0, "SSL for verify callback", - NULL, NULL, NULL); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + got_write_lock = 1; + + if (ssl_x509_store_ctx_idx < 0) { + ssl_x509_store_ctx_idx = + X509_STORE_CTX_get_ex_new_index(0, + "SSL for verify callback", + NULL, NULL, NULL); + } } - } - if (got_write_lock) - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - else - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + if (got_write_lock) + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + else + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - return ssl_x509_store_ctx_idx; + return ssl_x509_store_ctx_idx; + } } -static void ssl_cert_set_default_md(CERT *cert) +void ssl_cert_set_default_md(CERT *cert) { /* Set digest values to defaults */ #ifndef OPENSSL_NO_DSA @@ -262,25 +283,47 @@ CERT *ssl_cert_dup(CERT *cert) } } ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; + ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; #endif for (i = 0; i < SSL_PKEY_NUM; i++) { - if (cert->pkeys[i].x509 != NULL) { - ret->pkeys[i].x509 = cert->pkeys[i].x509; - CRYPTO_add(&ret->pkeys[i].x509->references, 1, CRYPTO_LOCK_X509); + CERT_PKEY *cpk = cert->pkeys + i; + CERT_PKEY *rpk = ret->pkeys + i; + if (cpk->x509 != NULL) { + rpk->x509 = cpk->x509; + CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509); } - if (cert->pkeys[i].privatekey != NULL) { - ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; - CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, - CRYPTO_LOCK_EVP_PKEY); + if (cpk->privatekey != NULL) { + rpk->privatekey = cpk->privatekey; + CRYPTO_add(&cpk->privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY); } - } - /* - * ret->extra_certs *should* exist, but currently the own certificate - * chain is held inside SSL_CTX - */ + if (cpk->chain) { + rpk->chain = X509_chain_up_ref(cpk->chain); + if (!rpk->chain) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + goto err; + } + } + rpk->valid_flags = 0; +#ifndef OPENSSL_NO_TLSEXT + if (cert->pkeys[i].serverinfo != NULL) { + /* Just copy everything. */ + ret->pkeys[i].serverinfo = + OPENSSL_malloc(cert->pkeys[i].serverinfo_length); + if (ret->pkeys[i].serverinfo == NULL) { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->pkeys[i].serverinfo_length = + cert->pkeys[i].serverinfo_length; + memcpy(ret->pkeys[i].serverinfo, + cert->pkeys[i].serverinfo, + cert->pkeys[i].serverinfo_length); + } +#endif + } ret->references = 1; /* @@ -288,6 +331,64 @@ CERT *ssl_cert_dup(CERT *cert) * will be set during handshake. */ ssl_cert_set_default_md(ret); + /* Peer sigalgs set to NULL as we get these from handshake too */ + ret->peer_sigalgs = NULL; + ret->peer_sigalgslen = 0; + /* Configured sigalgs however we copy across */ + + if (cert->conf_sigalgs) { + ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); + if (!ret->conf_sigalgs) + goto err; + memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen); + ret->conf_sigalgslen = cert->conf_sigalgslen; + } else + ret->conf_sigalgs = NULL; + + if (cert->client_sigalgs) { + ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); + if (!ret->client_sigalgs) + goto err; + memcpy(ret->client_sigalgs, cert->client_sigalgs, + cert->client_sigalgslen); + ret->client_sigalgslen = cert->client_sigalgslen; + } else + ret->client_sigalgs = NULL; + /* Shared sigalgs also NULL */ + ret->shared_sigalgs = NULL; + /* Copy any custom client certificate types */ + if (cert->ctypes) { + ret->ctypes = OPENSSL_malloc(cert->ctype_num); + if (!ret->ctypes) + goto err; + memcpy(ret->ctypes, cert->ctypes, cert->ctype_num); + ret->ctype_num = cert->ctype_num; + } + + ret->cert_flags = cert->cert_flags; + + ret->cert_cb = cert->cert_cb; + ret->cert_cb_arg = cert->cert_cb_arg; + + if (cert->verify_store) { + CRYPTO_add(&cert->verify_store->references, 1, + CRYPTO_LOCK_X509_STORE); + ret->verify_store = cert->verify_store; + } + + if (cert->chain_store) { + CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE); + ret->chain_store = cert->chain_store; + } + + ret->ciphers_raw = NULL; + +#ifndef OPENSSL_NO_TLSEXT + if (!custom_exts_copy(&ret->cli_ext, &cert->cli_ext)) + goto err; + if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext)) + goto err; +#endif return (ret); @@ -307,16 +408,49 @@ CERT *ssl_cert_dup(CERT *cert) EC_KEY_free(ret->ecdh_tmp); #endif - for (i = 0; i < SSL_PKEY_NUM; i++) { - if (ret->pkeys[i].x509 != NULL) - X509_free(ret->pkeys[i].x509); - if (ret->pkeys[i].privatekey != NULL) - EVP_PKEY_free(ret->pkeys[i].privatekey); - } +#ifndef OPENSSL_NO_TLSEXT + custom_exts_free(&ret->cli_ext); + custom_exts_free(&ret->srv_ext); +#endif + + ssl_cert_clear_certs(ret); return NULL; } +/* Free up and clear all certificates and chains */ + +void ssl_cert_clear_certs(CERT *c) +{ + int i; + if (c == NULL) + return; + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509) { + X509_free(cpk->x509); + cpk->x509 = NULL; + } + if (cpk->privatekey) { + EVP_PKEY_free(cpk->privatekey); + cpk->privatekey = NULL; + } + if (cpk->chain) { + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = NULL; + } +#ifndef OPENSSL_NO_TLSEXT + if (cpk->serverinfo) { + OPENSSL_free(cpk->serverinfo); + cpk->serverinfo = NULL; + cpk->serverinfo_length = 0; + } +#endif + /* Clear all flags apart from explicit sign */ + cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN; + } +} + void ssl_cert_free(CERT *c) { int i; @@ -350,16 +484,27 @@ void ssl_cert_free(CERT *c) EC_KEY_free(c->ecdh_tmp); #endif - for (i = 0; i < SSL_PKEY_NUM; i++) { - if (c->pkeys[i].x509 != NULL) - X509_free(c->pkeys[i].x509); - if (c->pkeys[i].privatekey != NULL) - EVP_PKEY_free(c->pkeys[i].privatekey); -#if 0 - if (c->pkeys[i].publickey != NULL) - EVP_PKEY_free(c->pkeys[i].publickey); + ssl_cert_clear_certs(c); + if (c->peer_sigalgs) + OPENSSL_free(c->peer_sigalgs); + if (c->conf_sigalgs) + OPENSSL_free(c->conf_sigalgs); + if (c->client_sigalgs) + OPENSSL_free(c->client_sigalgs); + if (c->shared_sigalgs) + OPENSSL_free(c->shared_sigalgs); + if (c->ctypes) + OPENSSL_free(c->ctypes); + if (c->verify_store) + X509_STORE_free(c->verify_store); + if (c->chain_store) + X509_STORE_free(c->chain_store); + if (c->ciphers_raw) + OPENSSL_free(c->ciphers_raw); +#ifndef OPENSSL_NO_TLSEXT + custom_exts_free(&c->cli_ext); + custom_exts_free(&c->srv_ext); #endif - } OPENSSL_free(c); } @@ -388,6 +533,104 @@ int ssl_cert_inst(CERT **o) return (1); } +int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) +{ + CERT_PKEY *cpk = c->key; + if (!cpk) + return 0; + if (cpk->chain) + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = chain; + return 1; +} + +int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) +{ + STACK_OF(X509) *dchain; + if (!chain) + return ssl_cert_set0_chain(c, NULL); + dchain = X509_chain_up_ref(chain); + if (!dchain) + return 0; + if (!ssl_cert_set0_chain(c, dchain)) { + sk_X509_pop_free(dchain, X509_free); + return 0; + } + return 1; +} + +int ssl_cert_add0_chain_cert(CERT *c, X509 *x) +{ + CERT_PKEY *cpk = c->key; + if (!cpk) + return 0; + if (!cpk->chain) + cpk->chain = sk_X509_new_null(); + if (!cpk->chain || !sk_X509_push(cpk->chain, x)) + return 0; + return 1; +} + +int ssl_cert_add1_chain_cert(CERT *c, X509 *x) +{ + if (!ssl_cert_add0_chain_cert(c, x)) + return 0; + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + return 1; +} + +int ssl_cert_select_current(CERT *c, X509 *x) +{ + int i; + if (x == NULL) + return 0; + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509 == x && cpk->privatekey) { + c->key = cpk; + return 1; + } + } + + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) { + c->key = cpk; + return 1; + } + } + return 0; +} + +int ssl_cert_set_current(CERT *c, long op) +{ + int i, idx; + if (!c) + return 0; + if (op == SSL_CERT_SET_FIRST) + idx = 0; + else if (op == SSL_CERT_SET_NEXT) { + idx = (int)(c->key - c->pkeys + 1); + if (idx >= SSL_PKEY_NUM) + return 0; + } else + return 0; + for (i = idx; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509 && cpk->privatekey) { + c->key = cpk; + return 1; + } + } + return 0; +} + +void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg) +{ + c->cert_cb = cb; + c->cert_cb_arg = arg; +} + SESS_CERT *ssl_sess_cert_new(void) { SESS_CERT *ret; @@ -466,16 +709,24 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) { X509 *x; int i; + X509_STORE *verify_store; X509_STORE_CTX ctx; + if (s->cert->verify_store) + verify_store = s->cert->verify_store; + else + verify_store = s->ctx->cert_store; + if ((sk == NULL) || (sk_X509_num(sk) == 0)) return (0); x = sk_X509_value(sk, 0); - if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) { + if (!X509_STORE_CTX_init(&ctx, verify_store, x, sk)) { SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB); return (0); } + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s)); #if 0 if (SSL_get_verify_depth(s) >= 0) X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); @@ -797,3 +1048,210 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); return ret; } + +/* Add a certificate to a BUF_MEM structure */ + +static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) +{ + int n; + unsigned char *p; + + n = i2d_X509(x, NULL); + if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) { + SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB); + return 0; + } + p = (unsigned char *)&(buf->data[*l]); + l2n3(n, p); + i2d_X509(x, &p); + *l += n + 3; + + return 1; +} + +/* Add certificate chain to internal SSL BUF_MEM strcuture */ +int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) +{ + BUF_MEM *buf = s->init_buf; + int no_chain; + int i; + + X509 *x; + STACK_OF(X509) *extra_certs; + X509_STORE *chain_store; + + if (cpk) + x = cpk->x509; + else + x = NULL; + + if (s->cert->chain_store) + chain_store = s->cert->chain_store; + else + chain_store = s->ctx->cert_store; + + /* + * If we have a certificate specific chain use it, else use parent ctx. + */ + if (cpk && cpk->chain) + extra_certs = cpk->chain; + else + extra_certs = s->ctx->extra_certs; + + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) + no_chain = 1; + else + no_chain = 0; + + /* TLSv1 sends a chain with nothing in it, instead of an alert */ + if (!BUF_MEM_grow_clean(buf, 10)) { + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_BUF_LIB); + return 0; + } + if (x != NULL) { + if (no_chain) { + if (!ssl_add_cert_to_buf(buf, l, x)) + return 0; + } else { + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) { + SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB); + return (0); + } + X509_verify_cert(&xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { + x = sk_X509_value(xs_ctx.chain, i); + + if (!ssl_add_cert_to_buf(buf, l, x)) { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } + } + for (i = 0; i < sk_X509_num(extra_certs); i++) { + x = sk_X509_value(extra_certs, i); + if (!ssl_add_cert_to_buf(buf, l, x)) + return 0; + } + + return 1; +} + +/* Build a certificate chain for current certificate */ +int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) +{ + CERT_PKEY *cpk = c->key; + X509_STORE_CTX xs_ctx; + STACK_OF(X509) *chain = NULL, *untrusted = NULL; + X509 *x; + int i, rv = 0; + unsigned long error; + + if (!cpk->x509) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET); + goto err; + } + /* Rearranging and check the chain: add everything to a store */ + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) { + chain_store = X509_STORE_new(); + if (!chain_store) + goto err; + for (i = 0; i < sk_X509_num(cpk->chain); i++) { + x = sk_X509_value(cpk->chain, i); + if (!X509_STORE_add_cert(chain_store, x)) { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != + X509_R_CERT_ALREADY_IN_HASH_TABLE) + goto err; + ERR_clear_error(); + } + } + /* Add EE cert too: it might be self signed */ + if (!X509_STORE_add_cert(chain_store, cpk->x509)) { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) + goto err; + ERR_clear_error(); + } + } else { + if (c->chain_store) + chain_store = c->chain_store; + + if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) + untrusted = cpk->chain; + } + + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB); + goto err; + } + /* Set suite B flags if needed */ + X509_STORE_CTX_set_flags(&xs_ctx, + c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS); + + i = X509_verify_cert(&xs_ctx); + if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) { + if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) + ERR_clear_error(); + i = 1; + rv = 2; + } + if (i > 0) + chain = X509_STORE_CTX_get1_chain(&xs_ctx); + if (i <= 0) { + SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED); + i = X509_STORE_CTX_get_error(&xs_ctx); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(i)); + + X509_STORE_CTX_cleanup(&xs_ctx); + goto err; + } + X509_STORE_CTX_cleanup(&xs_ctx); + if (cpk->chain) + sk_X509_pop_free(cpk->chain, X509_free); + /* Remove EE certificate from chain */ + x = sk_X509_shift(chain); + X509_free(x); + if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) { + if (sk_X509_num(chain) > 0) { + /* See if last cert is self signed */ + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) { + x = sk_X509_pop(chain); + X509_free(x); + } + } + } + cpk->chain = chain; + if (rv == 0) + rv = 1; + err: + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) + X509_STORE_free(chain_store); + + return rv; +} + +int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) +{ + X509_STORE **pstore; + if (chain) + pstore = &c->chain_store; + else + pstore = &c->verify_store; + if (*pstore) + X509_STORE_free(*pstore); + *pstore = store; + if (ref && store) + CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + return 1; +} diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index cac525e86009..2cc9a4a21f75 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -245,13 +245,11 @@ static const SSL_CIPHER cipher_aliases[] = { */ {0, SSL_TXT_kRSA, 0, SSL_kRSA, 0, 0, 0, 0, 0, 0, 0, 0}, - /* no such ciphersuites supported! */ {0, SSL_TXT_kDHr, 0, SSL_kDHr, 0, 0, 0, 0, 0, 0, 0, 0}, - /* no such ciphersuites supported! */ {0, SSL_TXT_kDHd, 0, SSL_kDHd, 0, 0, 0, 0, 0, 0, 0, 0}, - /* no such ciphersuites supported! */ {0, SSL_TXT_kDH, 0, SSL_kDHr | SSL_kDHd, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, SSL_TXT_kEDH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_kEDH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_kDHE, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_DH, 0, SSL_kDHr | SSL_kDHd | SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -261,6 +259,7 @@ static const SSL_CIPHER cipher_aliases[] = { {0, SSL_TXT_kECDHe, 0, SSL_kECDHe, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_kECDH, 0, SSL_kECDHr | SSL_kECDHe, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_kEECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_kECDHE, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_ECDH, 0, SSL_kECDHr | SSL_kECDHe | SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -287,7 +286,9 @@ static const SSL_CIPHER cipher_aliases[] = { /* aliases combining key exchange and server authentication */ {0, SSL_TXT_EDH, 0, SSL_kEDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_DHE, 0, SSL_kEDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_EECDH, 0, SSL_kEECDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_ECDHE, 0, SSL_kEECDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_NULL, 0, 0, 0, SSL_eNULL, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_KRB5, 0, SSL_kKRB5, SSL_aKRB5, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_RSA, 0, SSL_kRSA, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0}, @@ -343,6 +344,25 @@ static const SSL_CIPHER cipher_aliases[] = { {0, SSL_TXT_HIGH, 0, 0, 0, 0, 0, 0, SSL_HIGH, 0, 0, 0}, /* FIPS 140-2 approved ciphersuite */ {0, SSL_TXT_FIPS, 0, 0, 0, ~SSL_eNULL, 0, 0, SSL_FIPS, 0, 0, 0}, + /* "DHE-" aliases to "EDH-" labels (for forward compatibility) */ + {0, SSL3_TXT_DHE_DSS_DES_40_CBC_SHA, 0, + SSL_kDHE, SSL_aDSS, SSL_DES, SSL_SHA1, SSL_SSLV3, SSL_EXPORT | SSL_EXP40, + 0, 0, 0,}, + {0, SSL3_TXT_DHE_DSS_DES_64_CBC_SHA, 0, + SSL_kDHE, SSL_aDSS, SSL_DES, SSL_SHA1, SSL_SSLV3, SSL_NOT_EXP | SSL_LOW, + 0, 0, 0,}, + {0, SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA, 0, + SSL_kDHE, SSL_aDSS, SSL_3DES, SSL_SHA1, SSL_SSLV3, + SSL_NOT_EXP | SSL_HIGH | SSL_FIPS, 0, 0, 0,}, + {0, SSL3_TXT_DHE_RSA_DES_40_CBC_SHA, 0, + SSL_kDHE, SSL_aRSA, SSL_DES, SSL_SHA1, SSL_SSLV3, SSL_EXPORT | SSL_EXP40, + 0, 0, 0,}, + {0, SSL3_TXT_DHE_RSA_DES_64_CBC_SHA, 0, + SSL_kDHE, SSL_aRSA, SSL_DES, SSL_SHA1, SSL_SSLV3, SSL_NOT_EXP | SSL_LOW, + 0, 0, 0,}, + {0, SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA, 0, + SSL_kDHE, SSL_aRSA, SSL_3DES, SSL_SHA1, SSL_SSLV3, + SSL_NOT_EXP | SSL_HIGH | SSL_FIPS, 0, 0, 0,}, }; /* @@ -638,6 +658,14 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, c->algorithm_mac == SSL_SHA1 && (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1"))) *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES128 && + c->algorithm_mac == SSL_SHA256 && + (evp = EVP_get_cipherbyname("AES-128-CBC-HMAC-SHA256"))) + *enc = evp, *md = NULL; + else if (c->algorithm_enc == SSL_AES256 && + c->algorithm_mac == SSL_SHA256 && + (evp = EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA256"))) + *enc = evp, *md = NULL; return (1); } else return (0); @@ -710,8 +738,6 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, #ifdef OPENSSL_NO_DSA *auth |= SSL_aDSS; #endif - *mkey |= SSL_kDHr | SSL_kDHd; /* no such ciphersuites supported! */ - *auth |= SSL_aDH; #ifdef OPENSSL_NO_DH *mkey |= SSL_kDHr | SSL_kDHd | SSL_kEDH; *auth |= SSL_aDH; @@ -997,6 +1023,10 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength); #endif +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (cipher_id && cipher_id != cp->id) + continue; +#endif if (algo_strength == SSL_EXP_MASK && SSL_C_IS_EXPORT(cp)) goto ok; if (alg_ssl == ~SSL_SSLV2 && cp->algorithm_ssl == SSL_SSLV2) @@ -1369,10 +1399,71 @@ static int ssl_cipher_process_rulestr(const char *rule_str, return (retval); } +#ifndef OPENSSL_NO_EC +static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c, + const char **prule_str) +{ + unsigned int suiteb_flags = 0, suiteb_comb2 = 0; + if (!strcmp(*prule_str, "SUITEB128")) + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS; + else if (!strcmp(*prule_str, "SUITEB128ONLY")) + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS_ONLY; + else if (!strcmp(*prule_str, "SUITEB128C2")) { + suiteb_comb2 = 1; + suiteb_flags = SSL_CERT_FLAG_SUITEB_128_LOS; + } else if (!strcmp(*prule_str, "SUITEB192")) + suiteb_flags = SSL_CERT_FLAG_SUITEB_192_LOS; + + if (suiteb_flags) { + c->cert_flags &= ~SSL_CERT_FLAG_SUITEB_128_LOS; + c->cert_flags |= suiteb_flags; + } else + suiteb_flags = c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS; + + if (!suiteb_flags) + return 1; + /* Check version: if TLS 1.2 ciphers allowed we can use Suite B */ + + if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) { + if (meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) + SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + else + SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + return 0; + } +# ifndef OPENSSL_NO_ECDH + switch (suiteb_flags) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + if (suiteb_comb2) + *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384"; + else + *prule_str = + "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384"; + break; + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *prule_str = "ECDHE-ECDSA-AES128-GCM-SHA256"; + break; + case SSL_CERT_FLAG_SUITEB_192_LOS: + *prule_str = "ECDHE-ECDSA-AES256-GCM-SHA384"; + break; + } + /* Set auto ECDH parameter determination */ + c->ecdh_tmp_auto = 1; + return 1; +# else + SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST, + SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE); + return 0; +# endif +} +#endif + STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER) **cipher_list, STACK_OF(SSL_CIPHER) **cipher_list_by_id, - const char *rule_str) + const char *rule_str, CERT *c) { int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, @@ -1387,6 +1478,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK */ if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL) return NULL; +#ifndef OPENSSL_NO_EC + if (!check_suiteb_cipher_list(ssl_method, c, &rule_str)) + return NULL; +#endif /* * To reduce the work to do we only want to process the compiled @@ -1854,6 +1949,26 @@ STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) return (ssl_comp_methods); } +STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths) +{ + STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods; + ssl_comp_methods = meths; + return old_meths; +} + +static void cmeth_free(SSL_COMP *cm) +{ + OPENSSL_free(cm); +} + +void SSL_COMP_free_compression_methods(void) +{ + STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods; + ssl_comp_methods = NULL; + sk_SSL_COMP_pop_free(old_meths, cmeth_free); +} + int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) { SSL_COMP *comp; @@ -1904,5 +2019,55 @@ const char *SSL_COMP_get_name(const COMP_METHOD *comp) return comp->name; return NULL; } - #endif +/* For a cipher return the index corresponding to the certificate type */ +int ssl_cipher_get_cert_index(const SSL_CIPHER *c) +{ + unsigned long alg_k, alg_a; + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + + if (alg_k & (SSL_kECDHr | SSL_kECDHe)) { + /* + * we don't need to look at SSL_kEECDH since no certificate is needed + * for anon ECDH and for authenticated EECDH, the check for the auth + * algorithm will set i correctly NOTE: For ECDH-RSA, we need an ECC + * not an RSA cert but for EECDH-RSA we need an RSA cert. Placing the + * checks for SSL_kECDH before RSA checks ensures the correct cert is + * chosen. + */ + return SSL_PKEY_ECC; + } else if (alg_a & SSL_aECDSA) + return SSL_PKEY_ECC; + else if (alg_k & SSL_kDHr) + return SSL_PKEY_DH_RSA; + else if (alg_k & SSL_kDHd) + return SSL_PKEY_DH_DSA; + else if (alg_a & SSL_aDSS) + return SSL_PKEY_DSA_SIGN; + else if (alg_a & SSL_aRSA) + return SSL_PKEY_RSA_ENC; + else if (alg_a & SSL_aKRB5) + /* VRS something else here? */ + return -1; + else if (alg_a & SSL_aGOST94) + return SSL_PKEY_GOST94; + else if (alg_a & SSL_aGOST01) + return SSL_PKEY_GOST01; + return -1; +} + +const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr) +{ + const SSL_CIPHER *c; + c = ssl->method->get_cipher_by_char(ptr); + if (c == NULL || c->valid == 0) + return NULL; + return c; +} + +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr) +{ + return ssl->method->get_cipher_by_char(ptr); +} diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c new file mode 100644 index 000000000000..5478840deae9 --- /dev/null +++ b/ssl/ssl_conf.c @@ -0,0 +1,683 @@ +/* + * ! \file ssl/ssl_conf.c \brief SSL configuration functions + */ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifdef REF_CHECK +# include <assert.h> +#endif +#include <stdio.h> +#include "ssl_locl.h" +#include <openssl/conf.h> +#include <openssl/objects.h> +#ifndef OPENSSL_NO_DH +# include <openssl/dh.h> +#endif + +/* + * structure holding name tables. This is used for pemitted elements in lists + * such as TLSv1 and single command line switches such as no_tls1 + */ + +typedef struct { + const char *name; + int namelen; + unsigned int name_flags; + unsigned long option_value; +} ssl_flag_tbl; + +/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */ +#define SSL_TFLAG_INV 0x1 +/* Flags refers to cert_flags not options */ +#define SSL_TFLAG_CERT 0x2 +/* Option can only be used for clients */ +#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT +/* Option can only be used for servers */ +#define SSL_TFLAG_SERVER SSL_CONF_FLAG_SERVER +#define SSL_TFLAG_BOTH (SSL_TFLAG_CLIENT|SSL_TFLAG_SERVER) + +#define SSL_FLAG_TBL(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_BOTH, flag} +#define SSL_FLAG_TBL_SRV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_SERVER, flag} +#define SSL_FLAG_TBL_CLI(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CLIENT, flag} +#define SSL_FLAG_TBL_INV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_BOTH, flag} +#define SSL_FLAG_TBL_SRV_INV(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_INV|SSL_TFLAG_SERVER, flag} +#define SSL_FLAG_TBL_CERT(str, flag) \ + {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} + +/* + * Opaque structure containing SSL configuration context. + */ + +struct ssl_conf_ctx_st { + /* + * Various flags indicating (among other things) which options we will + * recognise. + */ + unsigned int flags; + /* Prefix and length of commands */ + char *prefix; + size_t prefixlen; + /* SSL_CTX or SSL structure to perform operations on */ + SSL_CTX *ctx; + SSL *ssl; + /* Pointer to SSL or SSL_CTX options field or NULL if none */ + unsigned long *poptions; + /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ + unsigned int *pcert_flags; + /* Current flag table being worked on */ + const ssl_flag_tbl *tbl; + /* Size of table */ + size_t ntbl; +}; + +static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl, + const char *name, int namelen, int onoff) +{ + /* If name not relevant for context skip */ + if (!(cctx->flags & tbl->name_flags & SSL_TFLAG_BOTH)) + return 0; + if (namelen == -1) { + if (strcmp(tbl->name, name)) + return 0; + } else if (tbl->namelen != namelen + || strncasecmp(tbl->name, name, namelen)) + return 0; + if (cctx->poptions) { + if (tbl->name_flags & SSL_TFLAG_INV) + onoff ^= 1; + if (tbl->name_flags & SSL_TFLAG_CERT) { + if (onoff) + *cctx->pcert_flags |= tbl->option_value; + else + *cctx->pcert_flags &= ~tbl->option_value; + } else { + if (onoff) + *cctx->poptions |= tbl->option_value; + else + *cctx->poptions &= ~tbl->option_value; + } + } + return 1; +} + +static int ssl_set_option_list(const char *elem, int len, void *usr) +{ + SSL_CONF_CTX *cctx = usr; + size_t i; + const ssl_flag_tbl *tbl; + int onoff = 1; + /* + * len == -1 indicates not being called in list context, just for single + * command line switches, so don't allow +, -. + */ + if (elem == NULL) + return 0; + if (len != -1) { + if (*elem == '+') { + elem++; + len--; + onoff = 1; + } else if (*elem == '-') { + elem++; + len--; + onoff = 0; + } + } + for (i = 0, tbl = cctx->tbl; i < cctx->ntbl; i++, tbl++) { + if (ssl_match_option(cctx, tbl, elem, len, onoff)) + return 1; + } + return 0; +} + +/* Single command line switches with no argument e.g. -no_ssl3 */ +static int ctrl_str_option(SSL_CONF_CTX *cctx, const char *cmd) +{ + static const ssl_flag_tbl ssl_option_single[] = { + SSL_FLAG_TBL("no_ssl2", SSL_OP_NO_SSLv2), + SSL_FLAG_TBL("no_ssl3", SSL_OP_NO_SSLv3), + SSL_FLAG_TBL("no_tls1", SSL_OP_NO_TLSv1), + SSL_FLAG_TBL("no_tls1_1", SSL_OP_NO_TLSv1_1), + SSL_FLAG_TBL("no_tls1_2", SSL_OP_NO_TLSv1_2), + SSL_FLAG_TBL("bugs", SSL_OP_ALL), + SSL_FLAG_TBL("no_comp", SSL_OP_NO_COMPRESSION), + SSL_FLAG_TBL_SRV("ecdh_single", SSL_OP_SINGLE_ECDH_USE), +#ifndef OPENSSL_NO_TLSEXT + SSL_FLAG_TBL("no_ticket", SSL_OP_NO_TICKET), +#endif + SSL_FLAG_TBL_SRV("serverpref", SSL_OP_CIPHER_SERVER_PREFERENCE), + SSL_FLAG_TBL("legacy_renegotiation", + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), + SSL_FLAG_TBL_SRV("legacy_server_connect", + SSL_OP_LEGACY_SERVER_CONNECT), + SSL_FLAG_TBL_SRV("no_resumption_on_reneg", + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + SSL_FLAG_TBL_SRV_INV("no_legacy_server_connect", + SSL_OP_LEGACY_SERVER_CONNECT), + SSL_FLAG_TBL_CERT("strict", SSL_CERT_FLAG_TLS_STRICT), +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + SSL_FLAG_TBL_CERT("debug_broken_protocol", + SSL_CERT_FLAG_BROKEN_PROTOCOL), +#endif + }; + cctx->tbl = ssl_option_single; + cctx->ntbl = sizeof(ssl_option_single) / sizeof(ssl_flag_tbl); + return ssl_set_option_list(cmd, -1, cctx); +} + +/* Set supported signature algorithms */ +static int cmd_SignatureAlgorithms(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + +/* Set supported client signature algorithms */ +static int cmd_ClientSignatureAlgorithms(SSL_CONF_CTX *cctx, + const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_client_sigalgs_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_client_sigalgs_list(cctx->ctx, value); + return rv > 0; +} + +static int cmd_Curves(SSL_CONF_CTX *cctx, const char *value) +{ + int rv; + if (cctx->ssl) + rv = SSL_set1_curves_list(cctx->ssl, value); + /* NB: ctx == NULL performs syntax checking only */ + else + rv = SSL_CTX_set1_curves_list(cctx->ctx, value); + return rv > 0; +} + +#ifndef OPENSSL_NO_ECDH +/* ECDH temporary parameters */ +static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int onoff = -1, rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) + return -2; + if (cctx->flags & SSL_CONF_FLAG_FILE) { + if (*value == '+') { + onoff = 1; + value++; + } + if (*value == '-') { + onoff = 0; + value++; + } + if (!strcasecmp(value, "automatic")) { + if (onoff == -1) + onoff = 1; + } else if (onoff != -1) + return 0; + } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (!strcmp(value, "auto")) + onoff = 1; + } + + if (onoff != -1) { + if (cctx->ctx) + rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff); + else if (cctx->ssl) + rv = SSL_set_ecdh_auto(cctx->ssl, onoff); + } else { + EC_KEY *ecdh; + int nid; + nid = EC_curve_nist2nid(value); + if (nid == NID_undef) + nid = OBJ_sn2nid(value); + if (nid == 0) + return 0; + ecdh = EC_KEY_new_by_curve_name(nid); + if (!ecdh) + return 0; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh); + else if (cctx->ssl) + rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh); + EC_KEY_free(ecdh); + } + + return rv > 0; +} +#endif +static int cmd_CipherString(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (cctx->ctx) + rv = SSL_CTX_set_cipher_list(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_set_cipher_list(cctx->ssl, value); + return rv > 0; +} + +static int cmd_Protocol(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_protocol_list[] = { + SSL_FLAG_TBL_INV("ALL", SSL_OP_NO_SSL_MASK), + SSL_FLAG_TBL_INV("SSLv2", SSL_OP_NO_SSLv2), + SSL_FLAG_TBL_INV("SSLv3", SSL_OP_NO_SSLv3), + SSL_FLAG_TBL_INV("TLSv1", SSL_OP_NO_TLSv1), + SSL_FLAG_TBL_INV("TLSv1.1", SSL_OP_NO_TLSv1_1), + SSL_FLAG_TBL_INV("TLSv1.2", SSL_OP_NO_TLSv1_2) + }; + if (!(cctx->flags & SSL_CONF_FLAG_FILE)) + return -2; + cctx->tbl = ssl_protocol_list; + cctx->ntbl = sizeof(ssl_protocol_list) / sizeof(ssl_flag_tbl); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) +{ + static const ssl_flag_tbl ssl_option_list[] = { + SSL_FLAG_TBL_INV("SessionTicket", SSL_OP_NO_TICKET), + SSL_FLAG_TBL_INV("EmptyFragments", + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS), + SSL_FLAG_TBL("Bugs", SSL_OP_ALL), + SSL_FLAG_TBL_INV("Compression", SSL_OP_NO_COMPRESSION), + SSL_FLAG_TBL_SRV("ServerPreference", SSL_OP_CIPHER_SERVER_PREFERENCE), + SSL_FLAG_TBL_SRV("NoResumptionOnRenegotiation", + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION), + SSL_FLAG_TBL_SRV("DHSingle", SSL_OP_SINGLE_DH_USE), + SSL_FLAG_TBL_SRV("ECDHSingle", SSL_OP_SINGLE_ECDH_USE), + SSL_FLAG_TBL("UnsafeLegacyRenegotiation", + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION), + }; + if (!(cctx->flags & SSL_CONF_FLAG_FILE)) + return -2; + if (value == NULL) + return -3; + cctx->tbl = ssl_option_list; + cctx->ntbl = sizeof(ssl_option_list) / sizeof(ssl_flag_tbl); + return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); +} + +static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (cctx->ctx) + rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value); + if (cctx->ssl) + rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM); + return rv > 0; +} + +static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (cctx->ctx) + rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM); + if (cctx->ssl) + rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM); + return rv > 0; +} + +static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 1; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (!(cctx->flags & SSL_CONF_FLAG_SERVER)) + return -2; + if (cctx->ctx) + rv = SSL_CTX_use_serverinfo_file(cctx->ctx, value); + return rv > 0; +} + +#ifndef OPENSSL_NO_DH +static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) +{ + int rv = 0; + DH *dh = NULL; + BIO *in = NULL; + if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) + return -2; + if (cctx->ctx || cctx->ssl) { + in = BIO_new(BIO_s_file_internal()); + if (!in) + goto end; + if (BIO_read_filename(in, value) <= 0) + goto end; + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (!dh) + goto end; + } else + return 1; + if (cctx->ctx) + rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh); + if (cctx->ssl) + rv = SSL_set_tmp_dh(cctx->ssl, dh); + end: + if (dh) + DH_free(dh); + if (in) + BIO_free(in); + return rv > 0; +} +#endif +typedef struct { + int (*cmd) (SSL_CONF_CTX *cctx, const char *value); + const char *str_file; + const char *str_cmdline; + unsigned int value_type; +} ssl_conf_cmd_tbl; + +/* Table of supported parameters */ + +#define SSL_CONF_CMD(name, cmdopt, type) \ + {cmd_##name, #name, cmdopt, type} + +#define SSL_CONF_CMD_STRING(name, cmdopt) \ + SSL_CONF_CMD(name, cmdopt, SSL_CONF_TYPE_STRING) + +static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { + SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs"), + SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs"), + SSL_CONF_CMD_STRING(Curves, "curves"), +#ifndef OPENSSL_NO_ECDH + SSL_CONF_CMD_STRING(ECDHParameters, "named_curve"), +#endif + SSL_CONF_CMD_STRING(CipherString, "cipher"), + SSL_CONF_CMD_STRING(Protocol, NULL), + SSL_CONF_CMD_STRING(Options, NULL), + SSL_CONF_CMD(Certificate, "cert", SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_TYPE_FILE), + SSL_CONF_CMD(ServerInfoFile, NULL, SSL_CONF_TYPE_FILE), +#ifndef OPENSSL_NO_DH + SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_TYPE_FILE) +#endif +}; + +static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) +{ + if (!pcmd || !*pcmd) + return 0; + /* If a prefix is set, check and skip */ + if (cctx->prefix) { + if (strlen(*pcmd) <= cctx->prefixlen) + return 0; + if (cctx->flags & SSL_CONF_FLAG_CMDLINE && + strncmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + if (cctx->flags & SSL_CONF_FLAG_FILE && + strncasecmp(*pcmd, cctx->prefix, cctx->prefixlen)) + return 0; + *pcmd += cctx->prefixlen; + } else if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (**pcmd != '-' || !(*pcmd)[1]) + return 0; + *pcmd += 1; + } + return 1; +} + +static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx, + const char *cmd) +{ + const ssl_conf_cmd_tbl *t; + size_t i; + if (cmd == NULL) + return NULL; + + /* Look for matching parameter name in table */ + for (i = 0, t = ssl_conf_cmds; + i < sizeof(ssl_conf_cmds) / sizeof(ssl_conf_cmd_tbl); i++, t++) { + if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (t->str_cmdline && !strcmp(t->str_cmdline, cmd)) + return t; + } + if (cctx->flags & SSL_CONF_FLAG_FILE) { + if (t->str_file && !strcasecmp(t->str_file, cmd)) + return t; + } + } + return NULL; +} + +int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) +{ + const ssl_conf_cmd_tbl *runcmd; + if (cmd == NULL) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_INVALID_NULL_CMD_NAME); + return 0; + } + + if (!ssl_conf_cmd_skip_prefix(cctx, &cmd)) + return -2; + + runcmd = ssl_conf_cmd_lookup(cctx, cmd); + + if (runcmd) { + int rv; + if (value == NULL) + return -3; + rv = runcmd->cmd(cctx, value); + if (rv > 0) + return 2; + if (rv == -2) + return -2; + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_BAD_VALUE); + ERR_add_error_data(4, "cmd=", cmd, ", value=", value); + } + return 0; + } + + if (cctx->flags & SSL_CONF_FLAG_CMDLINE) { + if (ctrl_str_option(cctx, cmd)) + return 1; + } + + if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) { + SSLerr(SSL_F_SSL_CONF_CMD, SSL_R_UNKNOWN_CMD_NAME); + ERR_add_error_data(2, "cmd=", cmd); + } + + return -2; +} + +int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv) +{ + int rv; + const char *arg = NULL, *argn; + if (pargc && *pargc == 0) + return 0; + if (!pargc || *pargc > 0) + arg = **pargv; + if (arg == NULL) + return 0; + if (!pargc || *pargc > 1) + argn = (*pargv)[1]; + else + argn = NULL; + cctx->flags &= ~SSL_CONF_FLAG_FILE; + cctx->flags |= SSL_CONF_FLAG_CMDLINE; + rv = SSL_CONF_cmd(cctx, arg, argn); + if (rv > 0) { + /* Success: update pargc, pargv */ + (*pargv) += rv; + if (pargc) + (*pargc) -= rv; + return rv; + } + /* Unknown switch: indicate no arguments processed */ + if (rv == -2) + return 0; + /* Some error occurred processing command, return fatal error */ + if (rv == 0) + return -1; + return rv; +} + +int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) +{ + if (ssl_conf_cmd_skip_prefix(cctx, &cmd)) { + const ssl_conf_cmd_tbl *runcmd; + runcmd = ssl_conf_cmd_lookup(cctx, cmd); + if (runcmd) + return runcmd->value_type; + } + return SSL_CONF_TYPE_UNKNOWN; +} + +SSL_CONF_CTX *SSL_CONF_CTX_new(void) +{ + SSL_CONF_CTX *ret; + ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX)); + if (ret) { + ret->flags = 0; + ret->prefix = NULL; + ret->prefixlen = 0; + ret->ssl = NULL; + ret->ctx = NULL; + ret->poptions = NULL; + ret->pcert_flags = NULL; + ret->tbl = NULL; + ret->ntbl = 0; + } + return ret; +} + +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) +{ + return 1; +} + +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) +{ + if (cctx) { + if (cctx->prefix) + OPENSSL_free(cctx->prefix); + OPENSSL_free(cctx); + } +} + +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) +{ + cctx->flags |= flags; + return cctx->flags; +} + +unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags) +{ + cctx->flags &= ~flags; + return cctx->flags; +} + +int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre) +{ + char *tmp = NULL; + if (pre) { + tmp = BUF_strdup(pre); + if (tmp == NULL) + return 0; + } + if (cctx->prefix) + OPENSSL_free(cctx->prefix); + cctx->prefix = tmp; + if (tmp) + cctx->prefixlen = strlen(tmp); + else + cctx->prefixlen = 0; + return 1; +} + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) +{ + cctx->ssl = ssl; + cctx->ctx = NULL; + if (ssl) { + cctx->poptions = &ssl->options; + cctx->pcert_flags = &ssl->cert->cert_flags; + } else { + cctx->poptions = NULL; + cctx->pcert_flags = NULL; + } +} + +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) +{ + cctx->ctx = ctx; + cctx->ssl = NULL; + if (ctx) { + cctx->poptions = &ctx->options; + cctx->pcert_flags = &ctx->cert->cert_flags; + } else { + cctx->poptions = NULL; + cctx->pcert_flags = NULL; + } +} diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 88621b72500f..1a6030e6238d 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -1,6 +1,6 @@ /* ssl/ssl_err.c */ /* ==================================================================== - * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2015 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -70,55 +70,56 @@ # define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason) static ERR_STRING_DATA SSL_str_functs[] = { + {ERR_FUNC(SSL_F_CHECK_SUITEB_CIPHER_LIST), "CHECK_SUITEB_CIPHER_LIST"}, {ERR_FUNC(SSL_F_CLIENT_CERTIFICATE), "CLIENT_CERTIFICATE"}, {ERR_FUNC(SSL_F_CLIENT_FINISHED), "CLIENT_FINISHED"}, {ERR_FUNC(SSL_F_CLIENT_HELLO), "CLIENT_HELLO"}, {ERR_FUNC(SSL_F_CLIENT_MASTER_KEY), "CLIENT_MASTER_KEY"}, {ERR_FUNC(SSL_F_D2I_SSL_SESSION), "d2i_SSL_SESSION"}, - {ERR_FUNC(SSL_F_DO_DTLS1_WRITE), "DO_DTLS1_WRITE"}, + {ERR_FUNC(SSL_F_DO_DTLS1_WRITE), "do_dtls1_write"}, {ERR_FUNC(SSL_F_DO_SSL3_WRITE), "DO_SSL3_WRITE"}, - {ERR_FUNC(SSL_F_DTLS1_ACCEPT), "DTLS1_ACCEPT"}, + {ERR_FUNC(SSL_F_DTLS1_ACCEPT), "dtls1_accept"}, {ERR_FUNC(SSL_F_DTLS1_ADD_CERT_TO_BUF), "DTLS1_ADD_CERT_TO_BUF"}, {ERR_FUNC(SSL_F_DTLS1_BUFFER_RECORD), "DTLS1_BUFFER_RECORD"}, - {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM), "DTLS1_CHECK_TIMEOUT_NUM"}, - {ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO), "DTLS1_CLIENT_HELLO"}, - {ERR_FUNC(SSL_F_DTLS1_CONNECT), "DTLS1_CONNECT"}, - {ERR_FUNC(SSL_F_DTLS1_ENC), "DTLS1_ENC"}, + {ERR_FUNC(SSL_F_DTLS1_CHECK_TIMEOUT_NUM), "dtls1_check_timeout_num"}, + {ERR_FUNC(SSL_F_DTLS1_CLIENT_HELLO), "dtls1_client_hello"}, + {ERR_FUNC(SSL_F_DTLS1_CONNECT), "dtls1_connect"}, {ERR_FUNC(SSL_F_DTLS1_GET_HELLO_VERIFY), "DTLS1_GET_HELLO_VERIFY"}, - {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE), "DTLS1_GET_MESSAGE"}, + {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE), "dtls1_get_message"}, {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT), "DTLS1_GET_MESSAGE_FRAGMENT"}, - {ERR_FUNC(SSL_F_DTLS1_GET_RECORD), "DTLS1_GET_RECORD"}, - {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "DTLS1_HANDLE_TIMEOUT"}, - {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "DTLS1_HEARTBEAT"}, - {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"}, + {ERR_FUNC(SSL_F_DTLS1_GET_RECORD), "dtls1_get_record"}, + {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "dtls1_handle_timeout"}, + {ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "dtls1_heartbeat"}, + {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "dtls1_output_cert_chain"}, {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"}, - {ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "DTLS1_READ_BYTES"}, - {ERR_FUNC(SSL_F_DTLS1_READ_FAILED), "DTLS1_READ_FAILED"}, + {ERR_FUNC(SSL_F_DTLS1_READ_BYTES), "dtls1_read_bytes"}, + {ERR_FUNC(SSL_F_DTLS1_READ_FAILED), "dtls1_read_failed"}, {ERR_FUNC(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST), - "DTLS1_SEND_CERTIFICATE_REQUEST"}, + "dtls1_send_certificate_request"}, {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE), - "DTLS1_SEND_CLIENT_CERTIFICATE"}, + "dtls1_send_client_certificate"}, {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE), - "DTLS1_SEND_CLIENT_KEY_EXCHANGE"}, - {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY), "DTLS1_SEND_CLIENT_VERIFY"}, + "dtls1_send_client_key_exchange"}, + {ERR_FUNC(SSL_F_DTLS1_SEND_CLIENT_VERIFY), "dtls1_send_client_verify"}, {ERR_FUNC(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST), "DTLS1_SEND_HELLO_VERIFY_REQUEST"}, {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE), - "DTLS1_SEND_SERVER_CERTIFICATE"}, - {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO), "DTLS1_SEND_SERVER_HELLO"}, + "dtls1_send_server_certificate"}, + {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_HELLO), "dtls1_send_server_hello"}, {ERR_FUNC(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE), - "DTLS1_SEND_SERVER_KEY_EXCHANGE"}, + "dtls1_send_server_key_exchange"}, {ERR_FUNC(SSL_F_DTLS1_WRITE_APP_DATA_BYTES), - "DTLS1_WRITE_APP_DATA_BYTES"}, + "dtls1_write_app_data_bytes"}, {ERR_FUNC(SSL_F_GET_CLIENT_FINISHED), "GET_CLIENT_FINISHED"}, {ERR_FUNC(SSL_F_GET_CLIENT_HELLO), "GET_CLIENT_HELLO"}, {ERR_FUNC(SSL_F_GET_CLIENT_MASTER_KEY), "GET_CLIENT_MASTER_KEY"}, {ERR_FUNC(SSL_F_GET_SERVER_FINISHED), "GET_SERVER_FINISHED"}, {ERR_FUNC(SSL_F_GET_SERVER_HELLO), "GET_SERVER_HELLO"}, + {ERR_FUNC(SSL_F_GET_SERVER_STATIC_DH_KEY), "GET_SERVER_STATIC_DH_KEY"}, {ERR_FUNC(SSL_F_GET_SERVER_VERIFY), "GET_SERVER_VERIFY"}, {ERR_FUNC(SSL_F_I2D_SSL_SESSION), "i2d_SSL_SESSION"}, {ERR_FUNC(SSL_F_READ_N), "READ_N"}, @@ -126,119 +127,123 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SERVER_FINISH), "SERVER_FINISH"}, {ERR_FUNC(SSL_F_SERVER_HELLO), "SERVER_HELLO"}, {ERR_FUNC(SSL_F_SERVER_VERIFY), "SERVER_VERIFY"}, - {ERR_FUNC(SSL_F_SSL23_ACCEPT), "SSL23_ACCEPT"}, + {ERR_FUNC(SSL_F_SSL23_ACCEPT), "ssl23_accept"}, {ERR_FUNC(SSL_F_SSL23_CLIENT_HELLO), "SSL23_CLIENT_HELLO"}, - {ERR_FUNC(SSL_F_SSL23_CONNECT), "SSL23_CONNECT"}, + {ERR_FUNC(SSL_F_SSL23_CONNECT), "ssl23_connect"}, {ERR_FUNC(SSL_F_SSL23_GET_CLIENT_HELLO), "SSL23_GET_CLIENT_HELLO"}, {ERR_FUNC(SSL_F_SSL23_GET_SERVER_HELLO), "SSL23_GET_SERVER_HELLO"}, - {ERR_FUNC(SSL_F_SSL23_PEEK), "SSL23_PEEK"}, - {ERR_FUNC(SSL_F_SSL23_READ), "SSL23_READ"}, - {ERR_FUNC(SSL_F_SSL23_WRITE), "SSL23_WRITE"}, - {ERR_FUNC(SSL_F_SSL2_ACCEPT), "SSL2_ACCEPT"}, - {ERR_FUNC(SSL_F_SSL2_CONNECT), "SSL2_CONNECT"}, - {ERR_FUNC(SSL_F_SSL2_ENC_INIT), "SSL2_ENC_INIT"}, + {ERR_FUNC(SSL_F_SSL23_PEEK), "ssl23_peek"}, + {ERR_FUNC(SSL_F_SSL23_READ), "ssl23_read"}, + {ERR_FUNC(SSL_F_SSL23_WRITE), "ssl23_write"}, + {ERR_FUNC(SSL_F_SSL2_ACCEPT), "ssl2_accept"}, + {ERR_FUNC(SSL_F_SSL2_CONNECT), "ssl2_connect"}, + {ERR_FUNC(SSL_F_SSL2_ENC_INIT), "ssl2_enc_init"}, {ERR_FUNC(SSL_F_SSL2_GENERATE_KEY_MATERIAL), - "SSL2_GENERATE_KEY_MATERIAL"}, - {ERR_FUNC(SSL_F_SSL2_PEEK), "SSL2_PEEK"}, - {ERR_FUNC(SSL_F_SSL2_READ), "SSL2_READ"}, + "ssl2_generate_key_material"}, + {ERR_FUNC(SSL_F_SSL2_PEEK), "ssl2_peek"}, + {ERR_FUNC(SSL_F_SSL2_READ), "ssl2_read"}, {ERR_FUNC(SSL_F_SSL2_READ_INTERNAL), "SSL2_READ_INTERNAL"}, - {ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE), "SSL2_SET_CERTIFICATE"}, - {ERR_FUNC(SSL_F_SSL2_WRITE), "SSL2_WRITE"}, - {ERR_FUNC(SSL_F_SSL3_ACCEPT), "SSL3_ACCEPT"}, + {ERR_FUNC(SSL_F_SSL2_SET_CERTIFICATE), "ssl2_set_certificate"}, + {ERR_FUNC(SSL_F_SSL2_WRITE), "ssl2_write"}, + {ERR_FUNC(SSL_F_SSL3_ACCEPT), "ssl3_accept"}, {ERR_FUNC(SSL_F_SSL3_ADD_CERT_TO_BUF), "SSL3_ADD_CERT_TO_BUF"}, - {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL), "SSL3_CALLBACK_CTRL"}, - {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE), "SSL3_CHANGE_CIPHER_STATE"}, + {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL), "ssl3_callback_ctrl"}, + {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE), "ssl3_change_cipher_state"}, {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM), - "SSL3_CHECK_CERT_AND_ALGORITHM"}, - {ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO), "SSL3_CHECK_CLIENT_HELLO"}, - {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO), "SSL3_CLIENT_HELLO"}, - {ERR_FUNC(SSL_F_SSL3_CONNECT), "SSL3_CONNECT"}, - {ERR_FUNC(SSL_F_SSL3_CTRL), "SSL3_CTRL"}, - {ERR_FUNC(SSL_F_SSL3_CTX_CTRL), "SSL3_CTX_CTRL"}, + "ssl3_check_cert_and_algorithm"}, + {ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO), "ssl3_check_client_hello"}, + {ERR_FUNC(SSL_F_SSL3_CHECK_FINISHED), "SSL3_CHECK_FINISHED"}, + {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO), "ssl3_client_hello"}, + {ERR_FUNC(SSL_F_SSL3_CONNECT), "ssl3_connect"}, + {ERR_FUNC(SSL_F_SSL3_CTRL), "ssl3_ctrl"}, + {ERR_FUNC(SSL_F_SSL3_CTX_CTRL), "ssl3_ctx_ctrl"}, {ERR_FUNC(SSL_F_SSL3_DIGEST_CACHED_RECORDS), - "SSL3_DIGEST_CACHED_RECORDS"}, + "ssl3_digest_cached_records"}, {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC), - "SSL3_DO_CHANGE_CIPHER_SPEC"}, - {ERR_FUNC(SSL_F_SSL3_ENC), "SSL3_ENC"}, - {ERR_FUNC(SSL_F_SSL3_CHECK_FINISHED), "SSL3_CHECK_FINISHED"}, + "ssl3_do_change_cipher_spec"}, + {ERR_FUNC(SSL_F_SSL3_ENC), "ssl3_enc"}, {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK), "SSL3_GENERATE_KEY_BLOCK"}, {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST), - "SSL3_GET_CERTIFICATE_REQUEST"}, - {ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS), "SSL3_GET_CERT_STATUS"}, - {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY), "SSL3_GET_CERT_VERIFY"}, + "ssl3_get_certificate_request"}, + {ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS), "ssl3_get_cert_status"}, + {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY), "ssl3_get_cert_verify"}, {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE), - "SSL3_GET_CLIENT_CERTIFICATE"}, - {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO), "SSL3_GET_CLIENT_HELLO"}, + "ssl3_get_client_certificate"}, + {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO), "ssl3_get_client_hello"}, {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE), - "SSL3_GET_CLIENT_KEY_EXCHANGE"}, - {ERR_FUNC(SSL_F_SSL3_GET_FINISHED), "SSL3_GET_FINISHED"}, - {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE), "SSL3_GET_KEY_EXCHANGE"}, - {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE), "SSL3_GET_MESSAGE"}, + "ssl3_get_client_key_exchange"}, + {ERR_FUNC(SSL_F_SSL3_GET_FINISHED), "ssl3_get_finished"}, + {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE), "ssl3_get_key_exchange"}, + {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE), "ssl3_get_message"}, {ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET), - "SSL3_GET_NEW_SESSION_TICKET"}, - {ERR_FUNC(SSL_F_SSL3_GET_NEXT_PROTO), "SSL3_GET_NEXT_PROTO"}, + "ssl3_get_new_session_ticket"}, + {ERR_FUNC(SSL_F_SSL3_GET_NEXT_PROTO), "ssl3_get_next_proto"}, {ERR_FUNC(SSL_F_SSL3_GET_RECORD), "SSL3_GET_RECORD"}, {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE), - "SSL3_GET_SERVER_CERTIFICATE"}, - {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE), "SSL3_GET_SERVER_DONE"}, - {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO), "SSL3_GET_SERVER_HELLO"}, + "ssl3_get_server_certificate"}, + {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE), "ssl3_get_server_done"}, + {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO), "ssl3_get_server_hello"}, {ERR_FUNC(SSL_F_SSL3_HANDSHAKE_MAC), "ssl3_handshake_mac"}, {ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET), "SSL3_NEW_SESSION_TICKET"}, - {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN), "SSL3_OUTPUT_CERT_CHAIN"}, - {ERR_FUNC(SSL_F_SSL3_PEEK), "SSL3_PEEK"}, - {ERR_FUNC(SSL_F_SSL3_READ_BYTES), "SSL3_READ_BYTES"}, - {ERR_FUNC(SSL_F_SSL3_READ_N), "SSL3_READ_N"}, + {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN), "ssl3_output_cert_chain"}, + {ERR_FUNC(SSL_F_SSL3_PEEK), "ssl3_peek"}, + {ERR_FUNC(SSL_F_SSL3_READ_BYTES), "ssl3_read_bytes"}, + {ERR_FUNC(SSL_F_SSL3_READ_N), "ssl3_read_n"}, {ERR_FUNC(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST), - "SSL3_SEND_CERTIFICATE_REQUEST"}, + "ssl3_send_certificate_request"}, {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE), - "SSL3_SEND_CLIENT_CERTIFICATE"}, + "ssl3_send_client_certificate"}, {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE), - "SSL3_SEND_CLIENT_KEY_EXCHANGE"}, - {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY), "SSL3_SEND_CLIENT_VERIFY"}, + "ssl3_send_client_key_exchange"}, + {ERR_FUNC(SSL_F_SSL3_SEND_CLIENT_VERIFY), "ssl3_send_client_verify"}, {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_CERTIFICATE), - "SSL3_SEND_SERVER_CERTIFICATE"}, - {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO), "SSL3_SEND_SERVER_HELLO"}, + "ssl3_send_server_certificate"}, + {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_HELLO), "ssl3_send_server_hello"}, {ERR_FUNC(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE), - "SSL3_SEND_SERVER_KEY_EXCHANGE"}, - {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "SSL3_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "SSL3_SETUP_READ_BUFFER"}, - {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "SSL3_SETUP_WRITE_BUFFER"}, - {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "SSL3_WRITE_BYTES"}, - {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "SSL3_WRITE_PENDING"}, + "ssl3_send_server_key_exchange"}, + {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "ssl3_setup_key_block"}, + {ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "ssl3_setup_read_buffer"}, + {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "ssl3_setup_write_buffer"}, + {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "ssl3_write_bytes"}, + {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "ssl3_write_pending"}, + {ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "ssl_add_cert_chain"}, + {ERR_FUNC(SSL_F_SSL_ADD_CERT_TO_BUF), "SSL_ADD_CERT_TO_BUF"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT), - "SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"}, + "ssl_add_clienthello_renegotiate_ext"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT), - "SSL_ADD_CLIENTHELLO_TLSEXT"}, + "ssl_add_clienthello_tlsext"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT), - "SSL_ADD_CLIENTHELLO_USE_SRTP_EXT"}, + "ssl_add_clienthello_use_srtp_ext"}, {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK), "SSL_add_dir_cert_subjects_to_stack"}, {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK), "SSL_add_file_cert_subjects_to_stack"}, {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT), - "SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"}, + "ssl_add_serverhello_renegotiate_ext"}, {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT), - "SSL_ADD_SERVERHELLO_TLSEXT"}, + "ssl_add_serverhello_tlsext"}, {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT), - "SSL_ADD_SERVERHELLO_USE_SRTP_EXT"}, - {ERR_FUNC(SSL_F_SSL_BAD_METHOD), "SSL_BAD_METHOD"}, - {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST), "SSL_BYTES_TO_CIPHER_LIST"}, - {ERR_FUNC(SSL_F_SSL_CERT_DUP), "SSL_CERT_DUP"}, - {ERR_FUNC(SSL_F_SSL_CERT_INST), "SSL_CERT_INST"}, + "ssl_add_serverhello_use_srtp_ext"}, + {ERR_FUNC(SSL_F_SSL_BAD_METHOD), "ssl_bad_method"}, + {ERR_FUNC(SSL_F_SSL_BUILD_CERT_CHAIN), "ssl_build_cert_chain"}, + {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST), "ssl_bytes_to_cipher_list"}, + {ERR_FUNC(SSL_F_SSL_CERT_DUP), "ssl_cert_dup"}, + {ERR_FUNC(SSL_F_SSL_CERT_INST), "ssl_cert_inst"}, {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE), "SSL_CERT_INSTANTIATE"}, - {ERR_FUNC(SSL_F_SSL_CERT_NEW), "SSL_CERT_NEW"}, + {ERR_FUNC(SSL_F_SSL_CERT_NEW), "ssl_cert_new"}, {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY), "SSL_check_private_key"}, {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT), "SSL_CHECK_SERVERHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG), - "SSL_CHECK_SRVR_ECC_CERT_AND_ALG"}, + "ssl_check_srvr_ecc_cert_and_alg"}, {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR), "SSL_CIPHER_PROCESS_RULESTR"}, {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT), "SSL_CIPHER_STRENGTH_SORT"}, {ERR_FUNC(SSL_F_SSL_CLEAR), "SSL_clear"}, {ERR_FUNC(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD), "SSL_COMP_add_compression_method"}, - {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST), "SSL_CREATE_CIPHER_LIST"}, + {ERR_FUNC(SSL_F_SSL_CONF_CMD), "SSL_CONF_cmd"}, + {ERR_FUNC(SSL_F_SSL_CREATE_CIPHER_LIST), "ssl_create_cipher_list"}, {ERR_FUNC(SSL_F_SSL_CTRL), "SSL_ctrl"}, {ERR_FUNC(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY), "SSL_CTX_check_private_key"}, {ERR_FUNC(SSL_F_SSL_CTX_MAKE_PROFILES), "SSL_CTX_MAKE_PROFILES"}, @@ -270,41 +275,49 @@ static ERR_STRING_DATA SSL_str_functs[] = { "SSL_CTX_use_RSAPrivateKey_ASN1"}, {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE), "SSL_CTX_use_RSAPrivateKey_file"}, + {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO), "SSL_CTX_use_serverinfo"}, + {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO_FILE), + "SSL_CTX_use_serverinfo_file"}, {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE), "SSL_do_handshake"}, - {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "SSL_GET_NEW_SESSION"}, - {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION), "SSL_GET_PREV_SESSION"}, + {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "ssl_get_new_session"}, + {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION), "ssl_get_prev_session"}, + {ERR_FUNC(SSL_F_SSL_GET_SERVER_CERT_INDEX), "SSL_GET_SERVER_CERT_INDEX"}, {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT), "SSL_GET_SERVER_SEND_CERT"}, - {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY), "SSL_GET_SERVER_SEND_PKEY"}, - {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "SSL_GET_SIGN_PKEY"}, - {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "SSL_INIT_WBIO_BUFFER"}, + {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY), "ssl_get_server_send_pkey"}, + {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "ssl_get_sign_pkey"}, + {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "ssl_init_wbio_buffer"}, {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"}, {ERR_FUNC(SSL_F_SSL_NEW), "SSL_new"}, {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT), - "SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"}, + "ssl_parse_clienthello_renegotiate_ext"}, {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT), - "SSL_PARSE_CLIENTHELLO_TLSEXT"}, + "ssl_parse_clienthello_tlsext"}, {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT), - "SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT"}, + "ssl_parse_clienthello_use_srtp_ext"}, {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT), - "SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"}, + "ssl_parse_serverhello_renegotiate_ext"}, {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT), - "SSL_PARSE_SERVERHELLO_TLSEXT"}, + "ssl_parse_serverhello_tlsext"}, {ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT), - "SSL_PARSE_SERVERHELLO_USE_SRTP_EXT"}, + "ssl_parse_serverhello_use_srtp_ext"}, {ERR_FUNC(SSL_F_SSL_PEEK), "SSL_peek"}, {ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT), - "SSL_PREPARE_CLIENTHELLO_TLSEXT"}, + "ssl_prepare_clienthello_tlsext"}, {ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT), - "SSL_PREPARE_SERVERHELLO_TLSEXT"}, + "ssl_prepare_serverhello_tlsext"}, {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"}, {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT), "SSL_RSA_PRIVATE_DECRYPT"}, {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT), "SSL_RSA_PUBLIC_ENCRYPT"}, + {ERR_FUNC(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT), + "SSL_SCAN_CLIENTHELLO_TLSEXT"}, + {ERR_FUNC(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT), + "SSL_SCAN_SERVERHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"}, {ERR_FUNC(SSL_F_SSL_SESSION_NEW), "SSL_SESSION_new"}, {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"}, {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT), "SSL_SESSION_set1_id_context"}, - {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW), "SSL_SESS_CERT_NEW"}, + {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW), "ssl_sess_cert_new"}, {ERR_FUNC(SSL_F_SSL_SET_CERT), "SSL_SET_CERT"}, {ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST), "SSL_set_cipher_list"}, {ERR_FUNC(SSL_F_SSL_SET_FD), "SSL_set_fd"}, @@ -321,10 +334,10 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL_SHUTDOWN), "SSL_shutdown"}, {ERR_FUNC(SSL_F_SSL_SRP_CTX_INIT), "SSL_SRP_CTX_init"}, {ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION), - "SSL_UNDEFINED_CONST_FUNCTION"}, - {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION), "SSL_UNDEFINED_FUNCTION"}, + "ssl_undefined_const_function"}, + {ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION), "ssl_undefined_function"}, {ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION), - "SSL_UNDEFINED_VOID_FUNCTION"}, + "ssl_undefined_void_function"}, {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE), "SSL_use_certificate"}, {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1), "SSL_use_certificate_ASN1"}, {ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE), "SSL_use_certificate_file"}, @@ -337,22 +350,25 @@ static ERR_STRING_DATA SSL_str_functs[] = { "SSL_use_RSAPrivateKey_ASN1"}, {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE), "SSL_use_RSAPrivateKey_file"}, - {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "SSL_VERIFY_CERT_CHAIN"}, + {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "ssl_verify_cert_chain"}, {ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"}, + {ERR_FUNC(SSL_F_TLS12_CHECK_PEER_SIGALG), "tls12_check_peer_sigalg"}, {ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC), "tls1_cert_verify_mac"}, - {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "TLS1_CHANGE_CIPHER_STATE"}, + {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "tls1_change_cipher_state"}, {ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_TLSEXT"}, - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_ENC), "tls1_enc"}, {ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL), - "TLS1_EXPORT_KEYING_MATERIAL"}, - {ERR_FUNC(SSL_F_TLS1_HEARTBEAT), "SSL_F_TLS1_HEARTBEAT"}, + "tls1_export_keying_material"}, + {ERR_FUNC(SSL_F_TLS1_GET_CURVELIST), "TLS1_GET_CURVELIST"}, + {ERR_FUNC(SSL_F_TLS1_HEARTBEAT), "tls1_heartbeat"}, {ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT), "TLS1_PREPARE_CLIENTHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT), "TLS1_PREPARE_SERVERHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "tls1_setup_key_block"}, + {ERR_FUNC(SSL_F_TLS1_SET_SERVER_SIGALGS), "tls1_set_server_sigalgs"}, {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, {0, NULL} }; @@ -365,6 +381,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE), "bad authentication type"}, {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC), "bad change cipher spec"}, {ERR_REASON(SSL_R_BAD_CHECKSUM), "bad checksum"}, + {ERR_REASON(SSL_R_BAD_DATA), "bad data"}, {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK), "bad data returned by callback"}, {ERR_REASON(SSL_R_BAD_DECOMPRESSION), "bad decompression"}, @@ -407,6 +424,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH), "bad ssl session id length"}, {ERR_REASON(SSL_R_BAD_STATE), "bad state"}, + {ERR_REASON(SSL_R_BAD_VALUE), "bad value"}, {ERR_REASON(SSL_R_BAD_WRITE_RETRY), "bad write retry"}, {ERR_REASON(SSL_R_BIO_NOT_SET), "bio not set"}, {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG), @@ -417,6 +435,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY), "ccs received early"}, {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED), "certificate verify failed"}, + {ERR_REASON(SSL_R_CERT_CB_ERROR), "cert cb error"}, {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH), "cert length mismatch"}, {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT), "challenge is different"}, {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH), "cipher code wrong length"}, @@ -455,6 +474,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = { "ecc cert should have rsa signature"}, {ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE), "ecc cert should have sha1 signature"}, + {ERR_REASON(SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE), + "ecdh required for suiteb mode"}, {ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER), "ecgroup too large for cipher"}, {ERR_REASON(SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST), @@ -475,13 +496,16 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST), "https proxy request"}, {ERR_REASON(SSL_R_HTTP_REQUEST), "http request"}, {ERR_REASON(SSL_R_ILLEGAL_PADDING), "illegal padding"}, + {ERR_REASON(SSL_R_ILLEGAL_SUITEB_DIGEST), "illegal Suite B digest"}, {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK), "inappropriate fallback"}, {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION), "inconsistent compression"}, {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH), "invalid challenge length"}, {ERR_REASON(SSL_R_INVALID_COMMAND), "invalid command"}, {ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM), "invalid compression algorithm"}, + {ERR_REASON(SSL_R_INVALID_NULL_CMD_NAME), "invalid null cmd name"}, {ERR_REASON(SSL_R_INVALID_PURPOSE), "invalid purpose"}, + {ERR_REASON(SSL_R_INVALID_SERVERINFO_DATA), "invalid serverinfo data"}, {ERR_REASON(SSL_R_INVALID_SRP_USERNAME), "invalid srp username"}, {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE), "invalid status response"}, {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH), @@ -508,6 +532,9 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_MISSING_DH_KEY), "missing dh key"}, {ERR_REASON(SSL_R_MISSING_DH_RSA_CERT), "missing dh rsa cert"}, {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT), "missing dsa signing cert"}, + {ERR_REASON(SSL_R_MISSING_ECDH_CERT), "missing ecdh cert"}, + {ERR_REASON(SSL_R_MISSING_ECDSA_SIGNING_CERT), + "missing ecdsa signing cert"}, {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY), "missing export tmp dh key"}, {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY), @@ -540,6 +567,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER), "Peer haven't sent GOST certificate, required for selected ciphersuite"}, {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED), "no method specified"}, + {ERR_REASON(SSL_R_NO_PEM_EXTENSIONS), "no pem extensions"}, {ERR_REASON(SSL_R_NO_PRIVATEKEY), "no privatekey"}, {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED), "no private key assigned"}, {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE), "no protocols available"}, @@ -548,6 +576,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST), "digest requred for handshake isn't computed"}, {ERR_REASON(SSL_R_NO_SHARED_CIPHER), "no shared cipher"}, + {ERR_REASON(SSL_R_NO_SHARED_SIGATURE_ALGORITHMS), + "no shared sigature algorithms"}, {ERR_REASON(SSL_R_NO_SRTP_PROFILES), "no srtp profiles"}, {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK), "no verify callback"}, {ERR_REASON(SSL_R_NULL_SSL_CTX), "null ssl ctx"}, @@ -556,6 +586,10 @@ static ERR_STRING_DATA SSL_str_reasons[] = { "old session cipher not returned"}, {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED), "old session compression algorithm not returned"}, + {ERR_REASON(SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE), + "only DTLS 1.2 allowed in Suite B mode"}, + {ERR_REASON(SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE), + "only TLS 1.2 allowed in Suite B mode"}, {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE), "only tls allowed in fips mode"}, {ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG), @@ -572,6 +606,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER), "peer error no cipher"}, {ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE), "peer error unsupported certificate type"}, + {ERR_REASON(SSL_R_PEM_NAME_BAD_PREFIX), "pem name bad prefix"}, + {ERR_REASON(SSL_R_PEM_NAME_TOO_SHORT), "pem name too short"}, {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG), "pre mac length too long"}, {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS), "problems mapping cipher functions"}, @@ -742,6 +778,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE), "unknown certificate type"}, {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED), "unknown cipher returned"}, {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE), "unknown cipher type"}, + {ERR_REASON(SSL_R_UNKNOWN_CMD_NAME), "unknown cmd name"}, {ERR_REASON(SSL_R_UNKNOWN_DIGEST), "unknown digest"}, {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE), "unknown key exchange type"}, @@ -764,7 +801,9 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE), "unsupported status type"}, {ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED), "use srtp not negotiated"}, {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET), "write bio not set"}, + {ERR_REASON(SSL_R_WRONG_CERTIFICATE_TYPE), "wrong certificate type"}, {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED), "wrong cipher returned"}, + {ERR_REASON(SSL_R_WRONG_CURVE), "wrong curve"}, {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE), "wrong message type"}, {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS), "wrong number of key bits"}, {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index e11746a69508..c0931e787728 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -273,7 +273,7 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) &(ctx->cipher_list_by_id), meth->version == SSL2_VERSION ? "SSLv2" : - SSL_DEFAULT_CIPHER_LIST); + SSL_DEFAULT_CIPHER_LIST, ctx->cert); if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); @@ -363,9 +363,39 @@ SSL *SSL_new(SSL_CTX *ctx) s->tlsext_ocsp_resplen = -1; CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); s->initial_ctx = ctx; +# ifndef OPENSSL_NO_EC + if (ctx->tlsext_ecpointformatlist) { + s->tlsext_ecpointformatlist = + BUF_memdup(ctx->tlsext_ecpointformatlist, + ctx->tlsext_ecpointformatlist_length); + if (!s->tlsext_ecpointformatlist) + goto err; + s->tlsext_ecpointformatlist_length = + ctx->tlsext_ecpointformatlist_length; + } + if (ctx->tlsext_ellipticcurvelist) { + s->tlsext_ellipticcurvelist = + BUF_memdup(ctx->tlsext_ellipticcurvelist, + ctx->tlsext_ellipticcurvelist_length); + if (!s->tlsext_ellipticcurvelist) + goto err; + s->tlsext_ellipticcurvelist_length = + ctx->tlsext_ellipticcurvelist_length; + } +# endif # ifndef OPENSSL_NO_NEXTPROTONEG s->next_proto_negotiated = NULL; # endif + + if (s->ctx->alpn_client_proto_list) { + s->alpn_client_proto_list = + OPENSSL_malloc(s->ctx->alpn_client_proto_list_len); + if (s->alpn_client_proto_list == NULL) + goto err; + memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list, + s->ctx->alpn_client_proto_list_len); + s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; + } #endif s->verify_result = X509_V_OK; @@ -505,6 +535,21 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) return X509_VERIFY_PARAM_set1(ssl->param, vpm); } +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) +{ + return ctx->param; +} + +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) +{ + return ssl->param; +} + +void SSL_certs_clear(SSL *s) +{ + ssl_cert_clear_certs(s->cert); +} + void SSL_free(SSL *s) { int i; @@ -585,6 +630,8 @@ void SSL_free(SSL *s) sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); if (s->tlsext_ocsp_resp) OPENSSL_free(s->tlsext_ocsp_resp); + if (s->alpn_client_proto_list) + OPENSSL_free(s->alpn_client_proto_list); #endif if (s->client_CA != NULL) @@ -1088,6 +1135,19 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) return s->s3->send_connection_binding; else return 0; + case SSL_CTRL_CERT_FLAGS: + return (s->cert->cert_flags |= larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return (s->cert->cert_flags &= ~larg); + + case SSL_CTRL_GET_RAW_CIPHERLIST: + if (parg) { + if (s->cert->ciphers_raw == NULL) + return 0; + *(unsigned char **)parg = s->cert->ciphers_raw; + return (int)s->cert->ciphers_rawlen; + } else + return ssl_put_cipher_by_char(s, NULL, NULL); default: return (s->method->ssl_ctrl(s, cmd, larg, parg)); } @@ -1116,6 +1176,20 @@ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { long l; + /* For some cases with ctx == NULL perform syntax checks */ + if (ctx == NULL) { + switch (cmd) { +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_CURVES_LIST: + return tls1_set_curves_list(NULL, NULL, parg); +#endif + case SSL_CTRL_SET_SIGALGS_LIST: + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(NULL, parg, 0); + default: + return 0; + } + } switch (cmd) { case SSL_CTRL_GET_READ_AHEAD: @@ -1186,6 +1260,10 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) return 0; ctx->max_send_fragment = larg; return 1; + case SSL_CTRL_CERT_FLAGS: + return (ctx->cert->cert_flags |= larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return (ctx->cert->cert_flags &= ~larg); default: return (ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg)); } @@ -1280,7 +1358,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) STACK_OF(SSL_CIPHER) *sk; sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, - &ctx->cipher_list_by_id, str); + &ctx->cipher_list_by_id, str, ctx->cert); /* * ssl_create_cipher_list may return an empty stack if it was unable to * find a cipher matching the given rule string (for example if the rule @@ -1303,7 +1381,7 @@ int SSL_set_cipher_list(SSL *s, const char *str) STACK_OF(SSL_CIPHER) *sk; sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, - &s->cipher_list_by_id, str); + &s->cipher_list_by_id, str, s->cert); /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) return 0; @@ -1358,10 +1436,11 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, { int i, j = 0; SSL_CIPHER *c; + CERT *ct = s->cert; unsigned char *q; -#ifndef OPENSSL_NO_KRB5 - int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx); -#endif /* OPENSSL_NO_KRB5 */ + int empty_reneg_info_scsv = !s->renegotiate; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); if (sk == NULL) return (0); @@ -1371,26 +1450,18 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { c = sk_SSL_CIPHER_value(sk, i); - /* Skip TLS v1.2 only ciphersuites if lower than v1.2 */ - if ((c->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_client_version(s) < TLS1_2_VERSION)) - continue; -#ifndef OPENSSL_NO_KRB5 - if (((c->algorithm_mkey & SSL_kKRB5) - || (c->algorithm_auth & SSL_aKRB5)) && nokrb5) + /* Skip disabled ciphers */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || c->algorithm_auth & ct->mask_a) continue; -#endif /* OPENSSL_NO_KRB5 */ -#ifndef OPENSSL_NO_PSK - /* with PSK there must be client callback set */ - if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) - && s->psk_client_callback == NULL) - continue; -#endif /* OPENSSL_NO_PSK */ -#ifndef OPENSSL_NO_SRP - if (((c->algorithm_mkey & SSL_kSRP) || (c->algorithm_auth & SSL_aSRP)) - && !(s->srp_ctx.srp_Mask & SSL_kSRP)) - continue; -#endif /* OPENSSL_NO_SRP */ +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (c->id == SSL3_CK_SCSV) { + if (!empty_reneg_info_scsv) + continue; + else + empty_reneg_info_scsv = 0; + } +#endif j = put_cb(c, p); p += j; } @@ -1399,7 +1470,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, * applicable SCSVs. */ if (p != q) { - if (!s->renegotiate) { + if (empty_reneg_info_scsv) { static SSL_CIPHER scsv = { 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1410,7 +1481,6 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n"); #endif } - if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) { static SSL_CIPHER scsv = { 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -1451,6 +1521,15 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, sk_SSL_CIPHER_zero(sk); } + if (s->cert->ciphers_raw) + OPENSSL_free(s->cert->ciphers_raw); + s->cert->ciphers_raw = BUF_memdup(p, num); + if (s->cert->ciphers_raw == NULL) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } + s->cert->ciphers_rawlen = (size_t)num; + for (i = 0; i < num; i += n) { /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ if (s->s3 && (n != 3 || !p[0]) && @@ -1534,7 +1613,6 @@ int SSL_get_servername_type(const SSL *s) return -1; } -# ifndef OPENSSL_NO_NEXTPROTONEG /* * SSL_select_next_proto implements the standard protocol selection. It is * expected that this function is called from the callback set by @@ -1594,6 +1672,7 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, return status; } +# ifndef OPENSSL_NO_NEXTPROTONEG /* * SSL_get0_next_proto_negotiated sets *data and *len to point to the * client's requested protocol for this connection and returns 0. If the @@ -1655,7 +1734,83 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, ctx->next_proto_select_cb_arg = arg; } # endif -#endif + +/* + * SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). Returns 0 on success. + */ +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned protos_len) +{ + if (ctx->alpn_client_proto_list) + OPENSSL_free(ctx->alpn_client_proto_list); + + ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len); + if (!ctx->alpn_client_proto_list) + return 1; + memcpy(ctx->alpn_client_proto_list, protos, protos_len); + ctx->alpn_client_proto_list_len = protos_len; + + return 0; +} + +/* + * SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). Returns 0 on success. + */ +int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned protos_len) +{ + if (ssl->alpn_client_proto_list) + OPENSSL_free(ssl->alpn_client_proto_list); + + ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len); + if (!ssl->alpn_client_proto_list) + return 1; + memcpy(ssl->alpn_client_proto_list, protos, protos_len); + ssl->alpn_client_proto_list_len = protos_len; + + return 0; +} + +/* + * SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is + * called during ClientHello processing in order to select an ALPN protocol + * from the client's list of offered protocols. + */ +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + ctx->alpn_select_cb = cb; + ctx->alpn_select_cb_arg = arg; +} + +/* + * SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from + * |ssl|. On return it sets |*data| to point to |*len| bytes of protocol name + * (not including the leading length-prefix byte). If the server didn't + * respond with a negotiated protocol then |*len| will be zero. + */ +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len) +{ + *data = NULL; + if (ssl->s3) + *data = ssl->s3->alpn_selected; + if (*data == NULL) + *len = 0; + else + *len = ssl->s3->alpn_selected_len; +} + +#endif /* !OPENSSL_NO_TLSEXT */ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, const char *label, size_t llen, @@ -1794,7 +1949,8 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ssl_create_cipher_list(ret->method, &ret->cipher_list, &ret->cipher_list_by_id, meth->version == - SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); + SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, + ret->cert); if (ret->cipher_list == NULL || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS); goto err2; @@ -2007,6 +2163,16 @@ void SSL_CTX_free(SSL_CTX *a) if (a->rbuf_freelist) ssl_buf_freelist_free(a->rbuf_freelist); #endif +#ifndef OPENSSL_NO_TLSEXT +# ifndef OPENSSL_NO_EC + if (a->tlsext_ecpointformatlist) + OPENSSL_free(a->tlsext_ecpointformatlist); + if (a->tlsext_ellipticcurvelist) + OPENSSL_free(a->tlsext_ellipticcurvelist); +# endif /* OPENSSL_NO_EC */ + if (a->alpn_client_proto_list != NULL) + OPENSSL_free(a->alpn_client_proto_list); +#endif OPENSSL_free(a); } @@ -2041,6 +2207,17 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) X509_VERIFY_PARAM_set_depth(ctx->param, depth); } +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), + void *arg) +{ + ssl_cert_set_cert_cb(c->cert, cb, arg); +} + +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg) +{ + ssl_cert_set_cert_cb(s->cert, cb, arg); +} + void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) { CERT_PKEY *cpk; @@ -2080,25 +2257,25 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) #endif #ifndef OPENSSL_NO_ECDH - have_ecdh_tmp = (c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL); + have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); #endif cpk = &(c->pkeys[SSL_PKEY_RSA_ENC]); - rsa_enc = (cpk->x509 != NULL && cpk->privatekey != NULL); + rsa_enc = cpk->valid_flags & CERT_PKEY_VALID; rsa_enc_export = (rsa_enc && EVP_PKEY_size(cpk->privatekey) * 8 <= kl); cpk = &(c->pkeys[SSL_PKEY_RSA_SIGN]); - rsa_sign = (cpk->x509 != NULL && cpk->privatekey != NULL); + rsa_sign = cpk->valid_flags & CERT_PKEY_SIGN; cpk = &(c->pkeys[SSL_PKEY_DSA_SIGN]); - dsa_sign = (cpk->x509 != NULL && cpk->privatekey != NULL); + dsa_sign = cpk->valid_flags & CERT_PKEY_SIGN; cpk = &(c->pkeys[SSL_PKEY_DH_RSA]); - dh_rsa = (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_rsa = cpk->valid_flags & CERT_PKEY_VALID; dh_rsa_export = (dh_rsa && EVP_PKEY_size(cpk->privatekey) * 8 <= kl); cpk = &(c->pkeys[SSL_PKEY_DH_DSA]); /* FIX THIS EAY EAY EAY */ - dh_dsa = (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_dsa = cpk->valid_flags & CERT_PKEY_VALID; dh_dsa_export = (dh_dsa && EVP_PKEY_size(cpk->privatekey) * 8 <= kl); cpk = &(c->pkeys[SSL_PKEY_ECC]); #ifndef OPENSSL_NO_EC - have_ecc_cert = (cpk->x509 != NULL && cpk->privatekey != NULL); + have_ecc_cert = cpk->valid_flags & CERT_PKEY_VALID; #endif mask_k = 0; mask_a = 0; @@ -2153,6 +2330,9 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) if (dh_dsa_export) emask_k |= SSL_kDHd; + if (mask_k & (SSL_kDHr | SSL_kDHd)) + mask_a |= SSL_aDH; + if (rsa_enc || rsa_sign) { mask_a |= SSL_aRSA; emask_a |= SSL_aRSA; @@ -2179,13 +2359,18 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) */ #ifndef OPENSSL_NO_EC if (have_ecc_cert) { + cpk = &c->pkeys[SSL_PKEY_ECC]; + x = cpk->x509; /* This call populates extension flags (ex_flags) */ - x = (c->pkeys[SSL_PKEY_ECC]).x509; X509_check_purpose(x, -1, 0); +# ifndef OPENSSL_NO_ECDH ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1; +# endif ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; + if (!(cpk->valid_flags & CERT_PKEY_SIGN)) + ecdsa_ok = 0; ecc_pkey = X509_get_pubkey(x); ecc_pkey_size = (ecc_pkey != NULL) ? EVP_PKEY_bits(ecc_pkey) : 0; EVP_PKEY_free(ecc_pkey); @@ -2193,7 +2378,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid); } -#ifndef OPENSSL_NO_ECDH +# ifndef OPENSSL_NO_ECDH if (ecdh_ok) { if (pk_nid == NID_rsaEncryption || pk_nid == NID_rsa) { @@ -2214,15 +2399,16 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) } } } -#endif -#ifndef OPENSSL_NO_ECDSA +# endif +# ifndef OPENSSL_NO_ECDSA if (ecdsa_ok) { mask_a |= SSL_aECDSA; emask_a |= SSL_aECDSA; } -#endif +# endif } #endif + #ifndef OPENSSL_NO_ECDH if (have_ecdh_tmp) { mask_k |= SSL_kEECDH; @@ -2317,65 +2503,44 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) #endif -/* THIS NEEDS CLEANING UP */ +static int ssl_get_server_cert_index(const SSL *s) +{ + int idx; + idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509) + idx = SSL_PKEY_RSA_SIGN; + if (idx == -1) + SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR); + return idx; +} + CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { - unsigned long alg_k, alg_a; CERT *c; int i; c = s->cert; + if (!s->s3 || !s->s3->tmp.new_cipher) + return NULL; ssl_set_cert_masks(c, s->s3->tmp.new_cipher); - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - alg_a = s->s3->tmp.new_cipher->algorithm_auth; - - if (alg_k & (SSL_kECDHr | SSL_kECDHe)) { - /* - * we don't need to look at SSL_kEECDH since no certificate is needed - * for anon ECDH and for authenticated EECDH, the check for the auth - * algorithm will set i correctly NOTE: For ECDH-RSA, we need an ECC - * not an RSA cert but for EECDH-RSA we need an RSA cert. Placing the - * checks for SSL_kECDH before RSA checks ensures the correct cert is - * chosen. - */ - i = SSL_PKEY_ECC; - } else if (alg_a & SSL_aECDSA) { - i = SSL_PKEY_ECC; - } else if (alg_k & SSL_kDHr) - i = SSL_PKEY_DH_RSA; - else if (alg_k & SSL_kDHd) - i = SSL_PKEY_DH_DSA; - else if (alg_a & SSL_aDSS) - i = SSL_PKEY_DSA_SIGN; - else if (alg_a & SSL_aRSA) { - if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) - i = SSL_PKEY_RSA_SIGN; - else - i = SSL_PKEY_RSA_ENC; - } else if (alg_a & SSL_aKRB5) { - /* VRS something else here? */ - return (NULL); - } else if (alg_a & SSL_aGOST94) - i = SSL_PKEY_GOST94; - else if (alg_a & SSL_aGOST01) - i = SSL_PKEY_GOST01; - else { /* if (alg_a & SSL_aNULL) */ - - SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY, ERR_R_INTERNAL_ERROR); - return (NULL); - } +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* + * Broken protocol test: return last used certificate: which may mismatch + * the one expected. + */ + if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) + return c->key; +#endif - return c->pkeys + i; -} + i = ssl_get_server_cert_index(s); -X509 *ssl_get_server_send_cert(const SSL *s) -{ - CERT_PKEY *cpk; - cpk = ssl_get_server_send_pkey(s); - if (!cpk) + /* This may or may not be an error. */ + if (i < 0) return NULL; - return cpk->x509; + + /* May be NULL. */ + return &c->pkeys[i]; } EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, @@ -2388,8 +2553,18 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, alg_a = cipher->algorithm_auth; c = s->cert; +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* + * Broken protocol test: use last key: which may mismatch the one + * expected. + */ + if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) + idx = c->key - c->pkeys; + else +#endif + if ((alg_a & SSL_aDSS) && - (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) + (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) idx = SSL_PKEY_DSA_SIGN; else if (alg_a & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) @@ -2408,6 +2583,28 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, return c->pkeys[idx].privatekey; } +#ifndef OPENSSL_NO_TLSEXT +int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, + size_t *serverinfo_length) +{ + CERT *c = NULL; + int i = 0; + *serverinfo_length = 0; + + c = s->cert; + i = ssl_get_server_cert_index(s); + + if (i == -1) + return 0; + if (c->pkeys[i].serverinfo == NULL) + return 0; + + *serverinfo = c->pkeys[i].serverinfo; + *serverinfo_length = c->pkeys[i].serverinfo_length; + return 1; +} +#endif + void ssl_update_cache(SSL *s, int mode) { int i; @@ -2439,6 +2636,11 @@ void ssl_update_cache(SSL *s, int mode) } } +const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx) +{ + return ctx->method; +} + const SSL_METHOD *SSL_get_ssl_method(SSL *s) { return (s->method); @@ -2634,6 +2836,12 @@ const char *SSL_get_version(const SSL *s) return ("SSLv3"); else if (s->version == SSL2_VERSION) return ("SSLv2"); + else if (s->version == DTLS1_BAD_VER) + return ("DTLSv0.9"); + else if (s->version == DTLS1_VERSION) + return ("DTLSv1"); + else if (s->version == DTLS1_2_VERSION) + return ("DTLSv1.2"); else return ("unknown"); } @@ -2784,7 +2992,6 @@ void ssl_clear_cipher_ctx(SSL *s) #endif } -/* Fix this function so that it takes an optional type parameter */ X509 *SSL_get_certificate(const SSL *s) { if (s->cert != NULL) @@ -2793,8 +3000,7 @@ X509 *SSL_get_certificate(const SSL *s) return (NULL); } -/* Fix this function so that it takes an optional type parameter */ -EVP_PKEY *SSL_get_privatekey(SSL *s) +EVP_PKEY *SSL_get_privatekey(const SSL *s) { if (s->cert != NULL) return (s->cert->key->privatekey); @@ -2802,6 +3008,22 @@ EVP_PKEY *SSL_get_privatekey(SSL *s) return (NULL); } +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) +{ + if (ctx->cert != NULL) + return ctx->cert->key->x509; + else + return NULL; +} + +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) +{ + if (ctx->cert != NULL) + return ctx->cert->key->privatekey; + else + return NULL; +} + const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) { if ((s->session != NULL) && (s->session->cipher != NULL)) @@ -2933,13 +3155,15 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) ctx = ssl->initial_ctx; #endif ssl->cert = ssl_cert_dup(ctx->cert); - if (ocert != NULL) { - int i; - /* Copy negotiated digests from original */ - for (i = 0; i < SSL_PKEY_NUM; i++) { - CERT_PKEY *cpk = ocert->pkeys + i; - CERT_PKEY *rpk = ssl->cert->pkeys + i; - rpk->digest = cpk->digest; + if (ocert) { + /* Preserve any already negotiated parameters */ + if (ssl->server) { + ssl->cert->peer_sigalgs = ocert->peer_sigalgs; + ssl->cert->peer_sigalgslen = ocert->peer_sigalgslen; + ocert->peer_sigalgs = NULL; + ssl->cert->ciphers_raw = ocert->ciphers_raw; + ssl->cert->ciphers_rawlen = ocert->ciphers_rawlen; + ocert->ciphers_raw = NULL; } ssl_cert_free(ocert); } @@ -3306,6 +3530,11 @@ int SSL_cache_hit(SSL *s) return s->hit; } +int SSL_is_server(SSL *s) +{ + return s->server; +} + #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) # include "../crypto/bio/bss_file.c" #endif diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index a7f3f8dad4aa..6c2c551e5e34 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -291,13 +291,13 @@ /* RSA key exchange */ # define SSL_kRSA 0x00000001L /* DH cert, RSA CA cert */ -/* no such ciphersuites supported! */ # define SSL_kDHr 0x00000002L /* DH cert, DSA CA cert */ -/* no such ciphersuite supported! */ # define SSL_kDHd 0x00000004L /* tmp DH key no DH cert */ # define SSL_kEDH 0x00000008L +/* forward-compatible synonym */ +# define SSL_kDHE SSL_kEDH /* Kerberos5 key exchange */ # define SSL_kKRB5 0x00000010L /* ECDH cert, RSA CA cert */ @@ -306,6 +306,8 @@ # define SSL_kECDHe 0x00000040L /* ephemeral ECDH */ # define SSL_kEECDH 0x00000080L +/* forward-compatible synonym */ +# define SSL_kECDHE SSL_kEECDH /* PSK */ # define SSL_kPSK 0x00000100L /* GOST key exchange */ @@ -321,7 +323,6 @@ /* no auth (i.e. use ADH or AECDH) */ # define SSL_aNULL 0x00000004L /* Fixed DH auth (kDHd or kDHr) */ -/* no such ciphersuites supported! */ # define SSL_aDH 0x00000008L /* Fixed ECDH auth (kECDHe or kECDHr) */ # define SSL_aECDH 0x00000010L @@ -465,6 +466,31 @@ (c)->algo_strength) # define SSL_C_EXPORT_PKEYLENGTH(c) SSL_EXPORT_PKEYLENGTH((c)->algo_strength) +/* Check if an SSL structure is using DTLS */ +# define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) +/* See if we need explicit IV */ +# define SSL_USE_EXPLICIT_IV(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV) +/* + * See if we use signature algorithms extension and signature algorithm + * before signatures. + */ +# define SSL_USE_SIGALGS(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS) +/* + * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. + */ +# define SSL_USE_TLS1_2_CIPHERS(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) +/* + * Determine if a client can use TLS 1.2 ciphersuites: can't rely on method + * flags because it may not be set to correct version yet. + */ +# define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \ + ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \ + (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION)) + /* Mostly for SSLv3 */ # define SSL_PKEY_RSA_ENC 0 # define SSL_PKEY_RSA_SIGN 1 @@ -505,7 +531,63 @@ typedef struct cert_pkey_st { EVP_PKEY *privatekey; /* Digest to use when signing */ const EVP_MD *digest; + /* Chain for this certificate */ + STACK_OF(X509) *chain; +# ifndef OPENSSL_NO_TLSEXT + /*- + * serverinfo data for this certificate. The data is in TLS Extension + * wire format, specifically it's a series of records like: + * uint16_t extension_type; // (RFC 5246, 7.4.1.4, Extension) + * uint16_t length; + * uint8_t data[length]; + */ + unsigned char *serverinfo; + size_t serverinfo_length; +# endif + /* + * Set if CERT_PKEY can be used with current SSL session: e.g. + * appropriate curve, signature algorithms etc. If zero it can't be used + * at all. + */ + int valid_flags; } CERT_PKEY; +/* Retrieve Suite B flags */ +# define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS) +/* Uses to check strict mode: suite B modes are always strict */ +# define SSL_CERT_FLAGS_CHECK_TLS_STRICT \ + (SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT) + +typedef struct { + unsigned short ext_type; + /* + * Per-connection flags relating to this extension type: not used if + * part of an SSL_CTX structure. + */ + unsigned short ext_flags; + custom_ext_add_cb add_cb; + custom_ext_free_cb free_cb; + void *add_arg; + custom_ext_parse_cb parse_cb; + void *parse_arg; +} custom_ext_method; + +/* ext_flags values */ + +/* + * Indicates an extension has been received. Used to check for unsolicited or + * duplicate extensions. + */ +# define SSL_EXT_FLAG_RECEIVED 0x1 +/* + * Indicates an extension has been sent: used to enable sending of + * corresponding ServerHello extension. + */ +# define SSL_EXT_FLAG_SENT 0x2 + +typedef struct { + custom_ext_method *meths; + size_t meths_count; +} custom_ext_methods; typedef struct cert_st { /* Current active set */ @@ -516,14 +598,17 @@ typedef struct cert_st { */ CERT_PKEY *key; /* - * The following masks are for the key and auth algorithms that are - * supported by the certs below + * For servers the following masks are for the key and auth algorithms + * that are supported by the certs below. For clients they are masks of + * *disabled* algorithms based on the current session. */ int valid; unsigned long mask_k; unsigned long mask_a; unsigned long export_mask_k; unsigned long export_mask_a; + /* Client only */ + unsigned long mask_ssl; # ifndef OPENSSL_NO_RSA RSA *rsa_tmp; RSA *(*rsa_tmp_cb) (SSL *ssl, int is_export, int keysize); @@ -536,8 +621,71 @@ typedef struct cert_st { EC_KEY *ecdh_tmp; /* Callback for generating ephemeral ECDH keys */ EC_KEY *(*ecdh_tmp_cb) (SSL *ssl, int is_export, int keysize); + /* Select ECDH parameters automatically */ + int ecdh_tmp_auto; # endif + /* Flags related to certificates */ + unsigned int cert_flags; CERT_PKEY pkeys[SSL_PKEY_NUM]; + /* + * Certificate types (received or sent) in certificate request message. + * On receive this is only set if number of certificate types exceeds + * SSL3_CT_NUMBER. + */ + unsigned char *ctypes; + size_t ctype_num; + /* + * signature algorithms peer reports: e.g. supported signature algorithms + * extension for server or as part of a certificate request for client. + */ + unsigned char *peer_sigalgs; + /* Size of above array */ + size_t peer_sigalgslen; + /* + * suppported signature algorithms. When set on a client this is sent in + * the client hello as the supported signature algorithms extension. For + * servers it represents the signature algorithms we are willing to use. + */ + unsigned char *conf_sigalgs; + /* Size of above array */ + size_t conf_sigalgslen; + /* + * Client authentication signature algorithms, if not set then uses + * conf_sigalgs. On servers these will be the signature algorithms sent + * to the client in a cerificate request for TLS 1.2. On a client this + * represents the signature algortithms we are willing to use for client + * authentication. + */ + unsigned char *client_sigalgs; + /* Size of above array */ + size_t client_sigalgslen; + /* + * Signature algorithms shared by client and server: cached because these + * are used most often. + */ + TLS_SIGALGS *shared_sigalgs; + size_t shared_sigalgslen; + /* + * Certificate setup callback: if set is called whenever a certificate + * may be required (client or server). the callback can then examine any + * appropriate parameters and setup any certificates required. This + * allows advanced applications to select certificates on the fly: for + * example based on supported signature algorithms or curves. + */ + int (*cert_cb) (SSL *ssl, void *arg); + void *cert_cb_arg; + /* + * Optional X509_STORE for chain building or certificate validation If + * NULL the parent SSL_CTX store is used instead. + */ + X509_STORE *chain_store; + X509_STORE *verify_store; + /* Raw values of the cipher list from a client */ + unsigned char *ciphers_raw; + size_t ciphers_rawlen; + /* Custom extension methods for server and client */ + custom_ext_methods cli_ext; + custom_ext_methods srv_ext; int references; /* >1 only if SSL_copy_session_id is used */ } CERT; @@ -563,6 +711,18 @@ typedef struct sess_cert_st { # endif int references; /* actually always 1 at the moment */ } SESS_CERT; +/* Structure containing decoded values of signature algorithms extension */ +struct tls_sigalgs_st { + /* NID of hash algorithm */ + int hash_nid; + /* NID of signature algorithm */ + int sign_nid; + /* Combined hash and signature NID */ + int signandhash_nid; + /* Raw values used in extension */ + unsigned char rsign; + unsigned char rhash; +}; /* * #define MAC_DEBUG @@ -596,8 +756,6 @@ typedef struct sess_cert_st { # define FP_ICC (int (*)(const void *,const void *)) # define ssl_put_cipher_by_char(ssl,ciph,ptr) \ ((ssl)->method->put_cipher_by_char((ciph),(ptr))) -# define ssl_get_cipher_by_char(ssl,ptr) \ - ((ssl)->method->get_cipher_by_char(ptr)) /* * This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit @@ -622,8 +780,39 @@ typedef struct ssl3_enc_method { const char *, size_t, const unsigned char *, size_t, int use_context); + /* Various flags indicating protocol version requirements */ + unsigned int enc_flags; + /* Handshake header length */ + unsigned int hhlen; + /* Set the handshake header */ + void (*set_handshake_header) (SSL *s, int type, unsigned long len); + /* Write out handshake message */ + int (*do_write) (SSL *s); } SSL3_ENC_METHOD; +# define SSL_HM_HEADER_LENGTH(s) s->method->ssl3_enc->hhlen +# define ssl_handshake_start(s) \ + (((unsigned char *)s->init_buf->data) + s->method->ssl3_enc->hhlen) +# define ssl_set_handshake_header(s, htype, len) \ + s->method->ssl3_enc->set_handshake_header(s, htype, len) +# define ssl_do_write(s) s->method->ssl3_enc->do_write(s) + +/* Values for enc_flags */ + +/* Uses explicit IV for CBC mode */ +# define SSL_ENC_FLAG_EXPLICIT_IV 0x1 +/* Uses signature algorithms extension */ +# define SSL_ENC_FLAG_SIGALGS 0x2 +/* Uses SHA256 default PRF */ +# define SSL_ENC_FLAG_SHA256_PRF 0x4 +/* Is DTLS */ +# define SSL_ENC_FLAG_DTLS 0x8 +/* + * Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. + */ +# define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10 + # ifndef OPENSSL_NO_COMP /* Used for holding the relevant compression methods loaded into SSL_CTX */ typedef struct ssl3_comp_st { @@ -653,13 +842,14 @@ OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[]; SSL_METHOD *ssl_bad_method(int ver); extern SSL3_ENC_METHOD TLSv1_enc_data; +extern SSL3_ENC_METHOD TLSv1_1_enc_data; +extern SSL3_ENC_METHOD TLSv1_2_enc_data; extern SSL3_ENC_METHOD SSLv3_enc_data; extern SSL3_ENC_METHOD DTLSv1_enc_data; - -# define SSL_IS_DTLS(s) (s->method->version == DTLS1_VERSION) +extern SSL3_ENC_METHOD DTLSv1_2_enc_data; # define IMPLEMENT_tls_meth_func(version, func_name, s_accept, s_connect, \ - s_get_meth) \ + s_get_meth, enc_data) \ const SSL_METHOD *func_name(void) \ { \ static const SSL_METHOD func_name##_data= { \ @@ -688,7 +878,7 @@ const SSL_METHOD *func_name(void) \ ssl3_get_cipher, \ s_get_meth, \ tls1_default_timeout, \ - &TLSv1_enc_data, \ + &enc_data, \ ssl_undefined_void_function, \ ssl3_callback_ctrl, \ ssl3_ctx_callback_ctrl, \ @@ -762,7 +952,7 @@ const SSL_METHOD *func_name(void) \ ssl23_get_cipher, \ s_get_meth, \ ssl23_default_timeout, \ - &ssl3_undef_enc_method, \ + &TLSv1_2_enc_data, \ ssl_undefined_void_function, \ ssl3_callback_ctrl, \ ssl3_ctx_callback_ctrl, \ @@ -807,11 +997,12 @@ const SSL_METHOD *func_name(void) \ return &func_name##_data; \ } -# define IMPLEMENT_dtls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \ +# define IMPLEMENT_dtls1_meth_func(version, func_name, s_accept, s_connect, \ + s_get_meth, enc_data) \ const SSL_METHOD *func_name(void) \ { \ static const SSL_METHOD func_name##_data= { \ - DTLS1_VERSION, \ + version, \ dtls1_new, \ dtls1_clear, \ dtls1_free, \ @@ -836,7 +1027,7 @@ const SSL_METHOD *func_name(void) \ dtls1_get_cipher, \ s_get_meth, \ dtls1_default_timeout, \ - &DTLSv1_enc_data, \ + &enc_data, \ ssl_undefined_void_function, \ ssl3_callback_ctrl, \ ssl3_ctx_callback_ctrl, \ @@ -857,7 +1048,9 @@ void ssl_clear_cipher_ctx(SSL *s); int ssl_clear_bad_session(SSL *s); CERT *ssl_cert_new(void); CERT *ssl_cert_dup(CERT *cert); +void ssl_cert_set_default_md(CERT *cert); int ssl_cert_inst(CERT **o); +void ssl_cert_clear_certs(CERT *c); void ssl_cert_free(CERT *c); SESS_CERT *ssl_sess_cert_new(void); void ssl_sess_cert_free(SESS_CERT *sc); @@ -880,18 +1073,36 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, STACK_OF(SSL_CIPHER) **pref, STACK_OF(SSL_CIPHER) **sorted, - const char *rule_str); + const char *rule_str, CERT *c); void ssl_update_cache(SSL *s, int mode); int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size, SSL_COMP **comp); int ssl_get_handshake_digest(int i, long *mask, const EVP_MD **md); +int ssl_cipher_get_cert_index(const SSL_CIPHER *c); +const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr); +int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain); +int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); +int ssl_cert_add0_chain_cert(CERT *c, X509 *x); +int ssl_cert_add1_chain_cert(CERT *c, X509 *x); +int ssl_cert_select_current(CERT *c, X509 *x); +int ssl_cert_set_current(CERT *c, long arg); +X509 *ssl_cert_get0_next_certificate(CERT *c, int first); +void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), + void *arg); + int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk); +int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l); +int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags); +int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref); int ssl_undefined_function(SSL *s); int ssl_undefined_void_function(void); int ssl_undefined_const_function(const SSL *s); CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); -X509 *ssl_get_server_send_cert(const SSL *); +# ifndef OPENSSL_NO_TLSEXT +int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, + size_t *serverinfo_length); +# endif EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c, const EVP_MD **pmd); int ssl_cert_type(X509 *x, EVP_PKEY *pkey); void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher); @@ -962,7 +1173,7 @@ void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len); int ssl3_enc(SSL *s, int send_data); int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data); void ssl3_free_digest_list(SSL *s); -unsigned long ssl3_output_cert_chain(SSL *s, X509 *x); +unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk); SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, STACK_OF(SSL_CIPHER) *srvr); int ssl3_setup_buffers(SSL *s); @@ -990,6 +1201,9 @@ void ssl3_record_sequence_update(unsigned char *seq); int ssl3_do_change_cipher_spec(SSL *ssl); long ssl3_default_timeout(void); +void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len); +int ssl3_handshake_write(SSL *s); + int ssl23_num_ciphers(void); const SSL_CIPHER *ssl23_get_cipher(unsigned int u); int ssl23_read(SSL *s, void *buf, int len); @@ -1017,8 +1231,6 @@ int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len); int dtls1_write_bytes(SSL *s, int type, const void *buf, int len); int dtls1_send_change_cipher_spec(SSL *s, int a, int b); -int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen); -unsigned long dtls1_output_cert_chain(SSL *s, X509 *x); int dtls1_read_failed(SSL *s, int code); int dtls1_buffer_message(SSL *s, int ccs); int dtls1_retransmit_message(SSL *s, unsigned short seq, @@ -1065,9 +1277,6 @@ int ssl3_send_next_proto(SSL *s); # endif int dtls1_client_hello(SSL *s); -int dtls1_send_client_certificate(SSL *s); -int dtls1_send_client_key_exchange(SSL *s); -int dtls1_send_client_verify(SSL *s); /* some server-only functions */ int ssl3_get_client_hello(SSL *s); @@ -1076,7 +1285,6 @@ int ssl3_send_hello_request(SSL *s); int ssl3_send_server_key_exchange(SSL *s); int ssl3_send_certificate_request(SSL *s); int ssl3_send_server_done(SSL *s); -int ssl3_check_client_hello(SSL *s); int ssl3_get_client_certificate(SSL *s); int ssl3_get_client_key_exchange(SSL *s); int ssl3_get_cert_verify(SSL *s); @@ -1084,13 +1292,6 @@ int ssl3_get_cert_verify(SSL *s); int ssl3_get_next_proto(SSL *s); # endif -int dtls1_send_hello_request(SSL *s); -int dtls1_send_server_hello(SSL *s); -int dtls1_send_server_certificate(SSL *s); -int dtls1_send_server_key_exchange(SSL *s); -int dtls1_send_certificate_request(SSL *s); -int dtls1_send_server_done(SSL *s); - int ssl23_accept(SSL *s); int ssl23_connect(SSL *s); int ssl23_read_bytes(SSL *s, int n); @@ -1115,7 +1316,6 @@ int dtls1_get_record(SSL *s); int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragement); int dtls1_dispatch_alert(SSL *s); -int dtls1_enc(SSL *s, int snd); int ssl_init_wbio_buffer(SSL *s, int push); void ssl_free_wbio_buffer(SSL *s); @@ -1146,22 +1346,33 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); # ifndef OPENSSL_NO_EC int tls1_ec_curve_id2nid(int curve_id); int tls1_ec_nid2curve_id(int nid); +int tls1_check_curve(SSL *s, const unsigned char *p, size_t len); +int tls1_shared_curve(SSL *s, int nmatch); +int tls1_set_curves(unsigned char **pext, size_t *pextlen, + int *curves, size_t ncurves); +int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, + const char *str); +# ifndef OPENSSL_NO_ECDH +int tls1_check_ec_tmp_key(SSL *s, unsigned long id); +# endif /* OPENSSL_NO_ECDH */ # endif /* OPENSSL_NO_EC */ # ifndef OPENSSL_NO_TLSEXT +int tls1_shared_list(SSL *s, + const unsigned char *l1, size_t l1len, + const unsigned char *l2, size_t l2len, int nmatch); unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, - unsigned char *limit); + unsigned char *limit, int *al); unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, - unsigned char *limit); + unsigned char *limit, int *al); int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, - unsigned char *d, int n, int *al); + unsigned char *d, int n); +int tls1_set_server_sigalgs(SSL *s); +int ssl_check_clienthello_tlsext_late(SSL *s); int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, - unsigned char *d, int n, int *al); + unsigned char *d, int n); int ssl_prepare_clienthello_tlsext(SSL *s); int ssl_prepare_serverhello_tlsext(SSL *s); -int ssl_check_clienthello_tlsext_early(SSL *s); -int ssl_check_clienthello_tlsext_late(SSL *s); -int ssl_check_serverhello_tlsext(SSL *s); # ifndef OPENSSL_NO_HEARTBEATS int tls1_heartbeat(SSL *s); @@ -1183,6 +1394,12 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, int tls12_get_sigid(const EVP_PKEY *pk); const EVP_MD *tls12_get_hash(unsigned char hash_alg); +int tls1_set_sigalgs_list(CERT *c, const char *str, int client); +int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen, int client); +int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, + int idx); +void tls1_set_cert_validity(SSL *s); + # endif EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md); void ssl_clear_hash_ctx(EVP_MD_CTX **hash); @@ -1195,8 +1412,12 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len, int *al); long ssl_get_algorithm2(SSL *s); -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize); -int tls12_get_req_sig_algs(SSL *s, unsigned char *p); +int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize); +int tls1_process_sigalgs(SSL *s); +size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs); +int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, + const unsigned char *sig, EVP_PKEY *pkey); +void ssl_set_client_disabled(SSL *s); int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen); @@ -1234,6 +1455,19 @@ void tls_fips_digest_extra(const EVP_CIPHER_CTX *cipher_ctx, int srp_verify_server_param(SSL *s, int *al); +/* t1_ext.c */ + +void custom_ext_init(custom_ext_methods *meths); + +int custom_ext_parse(SSL *s, int server, + unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, int *al); +int custom_ext_add(SSL *s, int server, + unsigned char **pret, unsigned char *limit, int *al); + +int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src); +void custom_exts_free(custom_ext_methods *exts); + # else # define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index daf15dd97e1c..b1b2318350a5 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -171,8 +171,22 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i; - - i = ssl_cert_type(NULL, pkey); + /* + * Special case for DH: check two DH certificate types for a match. This + * means for DH certificates we must set the certificate first. + */ + if (pkey->type == EVP_PKEY_DH) { + X509 *x; + i = -1; + x = c->pkeys[SSL_PKEY_DH_RSA].x509; + if (x && X509_check_private_key(x, pkey)) + i = SSL_PKEY_DH_RSA; + x = c->pkeys[SSL_PKEY_DH_DSA].x509; + if (i == -1 && x && X509_check_private_key(x, pkey)) + i = SSL_PKEY_DH_DSA; + ERR_clear_error(); + } else + i = ssl_cert_type(NULL, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return (0); @@ -690,16 +704,13 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) int r; unsigned long err; - if (ctx->extra_certs != NULL) { - sk_X509_pop_free(ctx->extra_certs, X509_free); - ctx->extra_certs = NULL; - } + SSL_CTX_clear_chain_certs(ctx); while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) != NULL) { - r = SSL_CTX_add_extra_chain_cert(ctx, ca); + r = SSL_CTX_add0_chain_cert(ctx, ca); if (!r) { X509_free(ca); ret = 0; @@ -728,3 +739,270 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) return (ret); } #endif + +#ifndef OPENSSL_NO_TLSEXT +static int serverinfo_find_extension(const unsigned char *serverinfo, + size_t serverinfo_length, + unsigned int extension_type, + const unsigned char **extension_data, + size_t *extension_length) +{ + *extension_data = NULL; + *extension_length = 0; + if (serverinfo == NULL || serverinfo_length == 0) + return 0; + for (;;) { + unsigned int type = 0; + size_t len = 0; + + /* end of serverinfo */ + if (serverinfo_length == 0) + return -1; /* Extension not found */ + + /* read 2-byte type field */ + if (serverinfo_length < 2) + return 0; /* Error */ + type = (serverinfo[0] << 8) + serverinfo[1]; + serverinfo += 2; + serverinfo_length -= 2; + + /* read 2-byte len field */ + if (serverinfo_length < 2) + return 0; /* Error */ + len = (serverinfo[0] << 8) + serverinfo[1]; + serverinfo += 2; + serverinfo_length -= 2; + + if (len > serverinfo_length) + return 0; /* Error */ + + if (type == extension_type) { + *extension_data = serverinfo; + *extension_length = len; + return 1; /* Success */ + } + + serverinfo += len; + serverinfo_length -= len; + } + return 0; /* Error */ +} + +static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + + if (inlen != 0) { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + + return 1; +} + +static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, size_t *outlen, + int *al, void *arg) +{ + const unsigned char *serverinfo = NULL; + size_t serverinfo_length = 0; + + /* Is there serverinfo data for the chosen server cert? */ + if ((ssl_get_server_cert_serverinfo(s, &serverinfo, + &serverinfo_length)) != 0) { + /* Find the relevant extension from the serverinfo */ + int retval = serverinfo_find_extension(serverinfo, serverinfo_length, + ext_type, out, outlen); + if (retval == 0) + return 0; /* Error */ + if (retval == -1) + return -1; /* No extension found, don't send extension */ + return 1; /* Send extension */ + } + return -1; /* No serverinfo data found, don't send + * extension */ +} + +/* + * With a NULL context, this function just checks that the serverinfo data + * parses correctly. With a non-NULL context, it registers callbacks for + * the included extensions. + */ +static int serverinfo_process_buffer(const unsigned char *serverinfo, + size_t serverinfo_length, SSL_CTX *ctx) +{ + if (serverinfo == NULL || serverinfo_length == 0) + return 0; + for (;;) { + unsigned int ext_type = 0; + size_t len = 0; + + /* end of serverinfo */ + if (serverinfo_length == 0) + return 1; + + /* read 2-byte type field */ + if (serverinfo_length < 2) + return 0; + /* FIXME: check for types we understand explicitly? */ + + /* Register callbacks for extensions */ + ext_type = (serverinfo[0] << 8) + serverinfo[1]; + if (ctx && !SSL_CTX_add_server_custom_ext(ctx, ext_type, + serverinfo_srv_add_cb, + NULL, NULL, + serverinfo_srv_parse_cb, + NULL)) + return 0; + + serverinfo += 2; + serverinfo_length -= 2; + + /* read 2-byte len field */ + if (serverinfo_length < 2) + return 0; + len = (serverinfo[0] << 8) + serverinfo[1]; + serverinfo += 2; + serverinfo_length -= 2; + + if (len > serverinfo_length) + return 0; + + serverinfo += len; + serverinfo_length -= len; + } +} + +int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length) +{ + if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA); + return 0; + } + if (!ssl_cert_inst(&ctx->cert)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE); + return 0; + } + if (ctx->cert->key == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_INTERNAL_ERROR); + return 0; + } + ctx->cert->key->serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, + serverinfo_length); + if (ctx->cert->key->serverinfo == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); + ctx->cert->key->serverinfo_length = serverinfo_length; + + /* + * Now that the serverinfo is validated and stored, go ahead and + * register callbacks. + */ + if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA); + return 0; + } + return 1; +} + +# ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) +{ + unsigned char *serverinfo = NULL; + size_t serverinfo_length = 0; + unsigned char *extension = 0; + long extension_length = 0; + char *name = NULL; + char *header = NULL; + char namePrefix[] = "SERVERINFO FOR "; + int ret = 0; + BIO *bin = NULL; + size_t num_extensions = 0; + + if (ctx == NULL || file == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + ERR_R_PASSED_NULL_PARAMETER); + goto end; + } + + bin = BIO_new(BIO_s_file_internal()); + if (bin == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB); + goto end; + } + if (BIO_read_filename(bin, file) <= 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB); + goto end; + } + + for (num_extensions = 0;; num_extensions++) { + if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) + == 0) { + /* + * There must be at least one extension in this file + */ + if (num_extensions == 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_NO_PEM_EXTENSIONS); + goto end; + } else /* End of file, we're done */ + break; + } + /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ + if (strlen(name) < strlen(namePrefix)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_PEM_NAME_TOO_SHORT); + goto end; + } + if (strncmp(name, namePrefix, strlen(namePrefix)) != 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, + SSL_R_PEM_NAME_BAD_PREFIX); + goto end; + } + /* + * Check that the decoded PEM data is plausible (valid length field) + */ + if (extension_length < 4 + || (extension[2] << 8) + extension[3] != extension_length - 4) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); + goto end; + } + /* Append the decoded extension to the serverinfo buffer */ + serverinfo = + OPENSSL_realloc(serverinfo, serverinfo_length + extension_length); + if (serverinfo == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); + goto end; + } + memcpy(serverinfo + serverinfo_length, extension, extension_length); + serverinfo_length += extension_length; + + OPENSSL_free(name); + name = NULL; + OPENSSL_free(header); + header = NULL; + OPENSSL_free(extension); + extension = NULL; + } + + ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length); + end: + /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(extension); + OPENSSL_free(serverinfo); + if (bin != NULL) + BIO_free(bin); + return ret; +} +# endif /* OPENSSL_NO_STDIO */ +#endif /* OPENSSL_NO_TLSEXT */ diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 1ad9dc79493c..07e7379abfd1 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -444,6 +444,9 @@ int ssl_get_new_session(SSL *s, int session) } else if (s->version == DTLS1_VERSION) { ss->ssl_version = DTLS1_VERSION; ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + } else if (s->version == DTLS1_2_VERSION) { + ss->ssl_version = DTLS1_2_VERSION; + ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; } else { SSLerr(SSL_F_SSL_GET_NEW_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION); SSL_SESSION_free(ss); @@ -519,38 +522,6 @@ int ssl_get_new_session(SSL *s, int session) return 0; } } -# ifndef OPENSSL_NO_EC - if (s->tlsext_ecpointformatlist) { - if (ss->tlsext_ecpointformatlist != NULL) - OPENSSL_free(ss->tlsext_ecpointformatlist); - if ((ss->tlsext_ecpointformatlist = - OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == - NULL) { - SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); - SSL_SESSION_free(ss); - return 0; - } - ss->tlsext_ecpointformatlist_length = - s->tlsext_ecpointformatlist_length; - memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, - s->tlsext_ecpointformatlist_length); - } - if (s->tlsext_ellipticcurvelist) { - if (ss->tlsext_ellipticcurvelist != NULL) - OPENSSL_free(ss->tlsext_ellipticcurvelist); - if ((ss->tlsext_ellipticcurvelist = - OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == - NULL) { - SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); - SSL_SESSION_free(ss); - return 0; - } - ss->tlsext_ellipticcurvelist_length = - s->tlsext_ellipticcurvelist_length; - memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, - s->tlsext_ellipticcurvelist_length); - } -# endif #endif } else { ss->session_id_length = 0; diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c index bd67dc70a951..45308d8b6587 100644 --- a/ssl/ssl_txt.c +++ b/ssl/ssl_txt.c @@ -124,6 +124,8 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) s = "TLSv1"; else if (x->ssl_version == DTLS1_VERSION) s = "DTLSv1"; + else if (x->ssl_version == DTLS1_2_VERSION) + s = "DTLSv1.2"; else if (x->ssl_version == DTLS1_BAD_VER) s = "DTLSv1-bad"; else diff --git a/ssl/ssltest.c b/ssl/ssltest.c index 6a0c293aa5ae..6737adf239c0 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -298,6 +298,362 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) static BIO *bio_err = NULL; static BIO *bio_stdout = NULL; +static const char *alpn_client; +static const char *alpn_server; +static const char *alpn_expected; +static unsigned char *alpn_selected; + +/*- + * next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL terminated string like "abc,def,ghi" + * + * returns: a malloced buffer or NULL on failure. + */ +static unsigned char *next_protos_parse(unsigned short *outlen, + const char *in) +{ + size_t len; + unsigned char *out; + size_t i, start = 0; + + len = strlen(in); + if (len >= 65535) + return NULL; + + out = OPENSSL_malloc(strlen(in) + 1); + if (!out) + return NULL; + + for (i = 0; i <= len; ++i) { + if (i == len || in[i] == ',') { + if (i - start > 255) { + OPENSSL_free(out); + return NULL; + } + out[start] = i - start; + start = i + 1; + } else + out[i + 1] = in[i]; + } + + *outlen = len + 1; + return out; +} + +static int cb_server_alpn(SSL *s, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg) +{ + unsigned char *protos; + unsigned short protos_len; + + protos = next_protos_parse(&protos_len, alpn_server); + if (protos == NULL) { + fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", + alpn_server); + abort(); + } + + if (SSL_select_next_proto + ((unsigned char **)out, outlen, protos, protos_len, in, + inlen) != OPENSSL_NPN_NEGOTIATED) { + OPENSSL_free(protos); + return SSL_TLSEXT_ERR_NOACK; + } + + /* + * Make a copy of the selected protocol which will be freed in + * verify_alpn. + */ + alpn_selected = OPENSSL_malloc(*outlen); + memcpy(alpn_selected, *out, *outlen); + *out = alpn_selected; + + OPENSSL_free(protos); + return SSL_TLSEXT_ERR_OK; +} + +static int verify_alpn(SSL *client, SSL *server) +{ + const unsigned char *client_proto, *server_proto; + unsigned int client_proto_len = 0, server_proto_len = 0; + SSL_get0_alpn_selected(client, &client_proto, &client_proto_len); + SSL_get0_alpn_selected(server, &server_proto, &server_proto_len); + + if (alpn_selected != NULL) { + OPENSSL_free(alpn_selected); + alpn_selected = NULL; + } + + if (client_proto_len != server_proto_len || + memcmp(client_proto, server_proto, client_proto_len) != 0) { + BIO_printf(bio_stdout, "ALPN selected protocols differ!\n"); + goto err; + } + + if (client_proto_len > 0 && alpn_expected == NULL) { + BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n"); + goto err; + } + + if (alpn_expected != NULL && + (client_proto_len != strlen(alpn_expected) || + memcmp(client_proto, alpn_expected, client_proto_len) != 0)) { + BIO_printf(bio_stdout, + "ALPN selected protocols not equal to expected protocol: %s\n", + alpn_expected); + goto err; + } + + return 0; + + err: + BIO_printf(bio_stdout, "ALPN results: client: '"); + BIO_write(bio_stdout, client_proto, client_proto_len); + BIO_printf(bio_stdout, "', server: '"); + BIO_write(bio_stdout, server_proto, server_proto_len); + BIO_printf(bio_stdout, "'\n"); + BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", + alpn_client, alpn_server); + return -1; +} + +#define SCT_EXT_TYPE 18 + +/* + * WARNING : below extension types are *NOT* IETF assigned, and could + * conflict if these types are reassigned and handled specially by OpenSSL + * in the future + */ +#define TACK_EXT_TYPE 62208 +#define CUSTOM_EXT_TYPE_0 1000 +#define CUSTOM_EXT_TYPE_1 1001 +#define CUSTOM_EXT_TYPE_2 1002 +#define CUSTOM_EXT_TYPE_3 1003 + +const char custom_ext_cli_string[] = "abc"; +const char custom_ext_srv_string[] = "defg"; + +/* These set from cmdline */ +char *serverinfo_file = NULL; +int serverinfo_sct = 0; +int serverinfo_tack = 0; + +/* These set based on extension callbacks */ +int serverinfo_sct_seen = 0; +int serverinfo_tack_seen = 0; +int serverinfo_other_seen = 0; + +/* This set from cmdline */ +int custom_ext = 0; + +/* This set based on extension callbacks */ +int custom_ext_error = 0; + +static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, size_t inlen, + int *al, void *arg) +{ + if (ext_type == SCT_EXT_TYPE) + serverinfo_sct_seen++; + else if (ext_type == TACK_EXT_TYPE) + serverinfo_tack_seen++; + else + serverinfo_other_seen++; + return 1; +} + +static int verify_serverinfo() +{ + if (serverinfo_sct != serverinfo_sct_seen) + return -1; + if (serverinfo_tack != serverinfo_tack_seen) + return -1; + if (serverinfo_other_seen) + return -1; + return 0; +} + +/*- + * Four test cases for custom extensions: + * 0 - no ClientHello extension or ServerHello response + * 1 - ClientHello with "abc", no response + * 2 - ClientHello with "abc", empty response + * 3 - ClientHello with "abc", "defg" response + */ + +static int custom_ext_0_cli_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_0) + custom_ext_error = 1; + return 0; /* Don't send an extension */ +} + +static int custom_ext_0_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + return 1; +} + +static int custom_ext_1_cli_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_1) + custom_ext_error = 1; + *out = (const unsigned char *)custom_ext_cli_string; + *outlen = strlen(custom_ext_cli_string); + return 1; /* Send "abc" */ +} + +static int custom_ext_1_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + return 1; +} + +static int custom_ext_2_cli_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_2) + custom_ext_error = 1; + *out = (const unsigned char *)custom_ext_cli_string; + *outlen = strlen(custom_ext_cli_string); + return 1; /* Send "abc" */ +} + +static int custom_ext_2_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_2) + custom_ext_error = 1; + if (inlen != 0) + custom_ext_error = 1; /* Should be empty response */ + return 1; +} + +static int custom_ext_3_cli_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_3) + custom_ext_error = 1; + *out = (const unsigned char *)custom_ext_cli_string; + *outlen = strlen(custom_ext_cli_string); + return 1; /* Send "abc" */ +} + +static int custom_ext_3_cli_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_3) + custom_ext_error = 1; + if (inlen != strlen(custom_ext_srv_string)) + custom_ext_error = 1; + if (memcmp(custom_ext_srv_string, in, inlen) != 0) + custom_ext_error = 1; /* Check for "defg" */ + return 1; +} + +/* + * custom_ext_0_cli_add_cb returns 0 - the server won't receive a callback + * for this extension + */ +static int custom_ext_0_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + custom_ext_error = 1; + return 1; +} + +/* 'add' callbacks are only called if the 'parse' callback is called */ +static int custom_ext_0_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + /* Error: should not have been called */ + custom_ext_error = 1; + return 0; /* Don't send an extension */ +} + +static int custom_ext_1_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_1) + custom_ext_error = 1; + /* Check for "abc" */ + if (inlen != strlen(custom_ext_cli_string)) + custom_ext_error = 1; + if (memcmp(in, custom_ext_cli_string, inlen) != 0) + custom_ext_error = 1; + return 1; +} + +static int custom_ext_1_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + return 0; /* Don't send an extension */ +} + +static int custom_ext_2_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_2) + custom_ext_error = 1; + /* Check for "abc" */ + if (inlen != strlen(custom_ext_cli_string)) + custom_ext_error = 1; + if (memcmp(in, custom_ext_cli_string, inlen) != 0) + custom_ext_error = 1; + return 1; +} + +static int custom_ext_2_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + *out = NULL; + *outlen = 0; + return 1; /* Send empty extension */ +} + +static int custom_ext_3_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +{ + if (ext_type != CUSTOM_EXT_TYPE_3) + custom_ext_error = 1; + /* Check for "abc" */ + if (inlen != strlen(custom_ext_cli_string)) + custom_ext_error = 1; + if (memcmp(in, custom_ext_cli_string, inlen) != 0) + custom_ext_error = 1; + return 1; +} + +static int custom_ext_3_srv_add_cb(SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *arg) +{ + *out = (const unsigned char *)custom_ext_srv_string; + *outlen = strlen(custom_ext_srv_string); + return 1; /* Send "defg" */ +} + static char *cipher = NULL; static int verbose = 0; static int debug = 0; @@ -327,7 +683,7 @@ static void sv_usage(void) fprintf(stderr, " -proxy - allow proxy certificates\n"); fprintf(stderr, " -proxy_auth <val> - set proxy policy rights\n"); fprintf(stderr, - " -proxy_cond <val> - experssion to test proxy policy rights\n"); + " -proxy_cond <val> - expression to test proxy policy rights\n"); fprintf(stderr, " -v - more output\n"); fprintf(stderr, " -d - debug output\n"); fprintf(stderr, " -reuse - use session-id reuse\n"); @@ -362,6 +718,10 @@ static void sv_usage(void) #ifndef OPENSSL_NO_TLS1 fprintf(stderr, " -tls1 - use TLSv1\n"); #endif +#ifndef OPENSSL_NO_DTLS + fprintf(stderr, " -dtls1 - use DTLSv1\n"); + fprintf(stderr, " -dtls12 - use DTLSv1.2\n"); +#endif fprintf(stderr, " -CApath arg - PEM format directory of CA's\n"); fprintf(stderr, " -CAfile arg - PEM format file of CA's\n"); fprintf(stderr, " -cert arg - Server certificate file\n"); @@ -387,6 +747,16 @@ static void sv_usage(void) " -test_cipherlist - Verifies the order of the ssl cipher lists.\n" " When this option is requested, the cipherlist\n" " tests are run instead of handshake tests.\n"); + fprintf(stderr, " -serverinfo_file file - have server use this file\n"); + fprintf(stderr, " -serverinfo_sct - have client offer and expect SCT\n"); + fprintf(stderr, + " -serverinfo_tack - have client offer and expect TACK\n"); + fprintf(stderr, + " -custom_ext - try various custom extension callbacks\n"); + fprintf(stderr, " -alpn_client <string> - have client side offer ALPN\n"); + fprintf(stderr, " -alpn_server <string> - have server side offer ALPN\n"); + fprintf(stderr, + " -alpn_expected <string> - the ALPN protocol that should be negotiated\n"); } static void print_details(SSL *c_ssl, const char *prefix) @@ -513,7 +883,7 @@ int main(int argc, char *argv[]) int badop = 0; int bio_pair = 0; int force = 0; - int tls1 = 0, ssl2 = 0, ssl3 = 0, ret = 1; + int dtls1 = 0, dtls12 = 0, tls1 = 0, ssl2 = 0, ssl3 = 0, ret = 1; int client_auth = 0; int server_auth = 0, i; struct app_verify_arg app_verify_arg = @@ -549,8 +919,8 @@ int main(int argc, char *argv[]) int no_psk = 0; int print_time = 0; clock_t s_time = 0, c_time = 0; - int comp = 0; #ifndef OPENSSL_NO_COMP + int comp = 0; COMP_METHOD *cm = NULL; STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; #endif @@ -592,7 +962,7 @@ int main(int argc, char *argv[]) fips_mode = 1; #else fprintf(stderr, - "not compiled with FIPS support, so exitting without running.\n"); + "not compiled with FIPS support, so exiting without running.\n"); EXIT(0); #endif } else if (strcmp(*argv, "-server_auth") == 0) @@ -673,6 +1043,16 @@ int main(int argc, char *argv[]) no_protocol = 1; #endif ssl3 = 1; + } else if (strcmp(*argv, "-dtls1") == 0) { +#ifdef OPENSSL_NO_DTLS + no_protocol = 1; +#endif + dtls1 = 1; + } else if (strcmp(*argv, "-dtls12") == 0) { +#ifdef OPENSSL_NO_DTLS + no_protocol = 1; +#endif + dtls12 = 1; } else if (strncmp(*argv, "-num", 4) == 0) { if (--argc < 1) goto bad; @@ -732,11 +1112,15 @@ int main(int argc, char *argv[]) force = 1; } else if (strcmp(*argv, "-time") == 0) { print_time = 1; - } else if (strcmp(*argv, "-zlib") == 0) { + } +#ifndef OPENSSL_NO_COMP + else if (strcmp(*argv, "-zlib") == 0) { comp = COMP_ZLIB; } else if (strcmp(*argv, "-rle") == 0) { comp = COMP_RLE; - } else if (strcmp(*argv, "-named_curve") == 0) { + } +#endif + else if (strcmp(*argv, "-named_curve") == 0) { if (--argc < 1) goto bad; #ifndef OPENSSL_NO_ECDH @@ -752,6 +1136,28 @@ int main(int argc, char *argv[]) app_verify_arg.allow_proxy_certs = 1; } else if (strcmp(*argv, "-test_cipherlist") == 0) { test_cipherlist = 1; + } else if (strcmp(*argv, "-serverinfo_sct") == 0) { + serverinfo_sct = 1; + } else if (strcmp(*argv, "-serverinfo_tack") == 0) { + serverinfo_tack = 1; + } else if (strcmp(*argv, "-serverinfo_file") == 0) { + if (--argc < 1) + goto bad; + serverinfo_file = *(++argv); + } else if (strcmp(*argv, "-custom_ext") == 0) { + custom_ext = 1; + } else if (strcmp(*argv, "-alpn_client") == 0) { + if (--argc < 1) + goto bad; + alpn_client = *(++argv); + } else if (strcmp(*argv, "-alpn_server") == 0) { + if (--argc < 1) + goto bad; + alpn_server = *(++argv); + } else if (strcmp(*argv, "-alpn_expected") == 0) { + if (--argc < 1) + goto bad; + alpn_expected = *(++argv); } else { fprintf(stderr, "unknown option %s\n", *argv); badop = 1; @@ -782,8 +1188,8 @@ int main(int argc, char *argv[]) goto end; } - if (ssl2 + ssl3 + tls1 > 1) { - fprintf(stderr, "At most one of -ssl2, -ssl3, or -tls1 should " + if (ssl2 + ssl3 + tls1 + dtls1 + dtls12 > 1) { + fprintf(stderr, "At most one of -ssl2, -ssl3, -tls1, -dtls1 or -dtls12 should " "be requested.\n"); EXIT(1); } @@ -800,10 +1206,10 @@ int main(int argc, char *argv[]) goto end; } - if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) { + if (!ssl2 && !ssl3 && !tls1 && !dtls1 && !dtls12 && number > 1 && !reuse && !force) { fprintf(stderr, "This case cannot work. Use -f to perform " "the test anyway (and\n-d to see what happens), " - "or add one of -ssl2, -ssl3, -tls1, -reuse\n" + "or add one of ssl2, -ssl3, -tls1, -dtls1, -dtls12, -reuse\n" "to avoid protocol mismatch.\n"); EXIT(1); } @@ -881,6 +1287,13 @@ int main(int argc, char *argv[]) meth = SSLv3_method(); else #endif +#ifndef OPENSSL_NO_DTLS + if (dtls1) + meth = DTLSv1_method(); + else if (dtls12) + meth = DTLSv1_2_method(); + else +#endif #ifndef OPENSSL_NO_TLS1 if (tls1) meth = TLSv1_method(); @@ -928,12 +1341,9 @@ int main(int argc, char *argv[]) BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); goto end; } - } else -# ifdef OPENSSL_NO_EC2M + } else { nid = NID_X9_62_prime256v1; -# else - nid = NID_sect163r2; -# endif + } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { @@ -1055,6 +1465,72 @@ int main(int argc, char *argv[]) } #endif + if (serverinfo_sct) + SSL_CTX_add_client_custom_ext(c_ctx, SCT_EXT_TYPE, + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL); + if (serverinfo_tack) + SSL_CTX_add_client_custom_ext(c_ctx, TACK_EXT_TYPE, + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL); + + if (serverinfo_file) + if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file)) { + BIO_printf(bio_err, "missing serverinfo file\n"); + goto end; + } + + if (custom_ext) { + SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_0, + custom_ext_0_cli_add_cb, + NULL, NULL, + custom_ext_0_cli_parse_cb, NULL); + SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_1, + custom_ext_1_cli_add_cb, + NULL, NULL, + custom_ext_1_cli_parse_cb, NULL); + SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_2, + custom_ext_2_cli_add_cb, + NULL, NULL, + custom_ext_2_cli_parse_cb, NULL); + SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_3, + custom_ext_3_cli_add_cb, + NULL, NULL, + custom_ext_3_cli_parse_cb, NULL); + + SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_0, + custom_ext_0_srv_add_cb, + NULL, NULL, + custom_ext_0_srv_parse_cb, NULL); + SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_1, + custom_ext_1_srv_add_cb, + NULL, NULL, + custom_ext_1_srv_parse_cb, NULL); + SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_2, + custom_ext_2_srv_add_cb, + NULL, NULL, + custom_ext_2_srv_parse_cb, NULL); + SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_3, + custom_ext_3_srv_add_cb, + NULL, NULL, + custom_ext_3_srv_parse_cb, NULL); + } + + if (alpn_server) + SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); + + if (alpn_client) { + unsigned short alpn_len; + unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); + + if (alpn == NULL) { + BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); + goto end; + } + SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len); + OPENSSL_free(alpn); + } + c_ssl = SSL_new(c_ctx); s_ssl = SSL_new(s_ctx); @@ -1479,6 +1955,21 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, if (verbose) print_details(c_ssl, "DONE via BIO pair: "); + + if (verify_serverinfo() < 0) { + ret = 1; + goto err; + } + if (verify_alpn(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; + } + + if (custom_ext_error) { + ret = 1; + goto err; + } + end: ret = 0; @@ -1508,7 +1999,8 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, int doit(SSL *s_ssl, SSL *c_ssl, long count) { - MS_STATIC char cbuf[1024 * 8], sbuf[1024 * 8]; + char *cbuf = NULL, *sbuf = NULL; + long bufsiz; long cw_num = count, cr_num = count; long sw_num = count, sr_num = count; int ret = 1; @@ -1521,9 +2013,17 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) int done = 0; int c_write, s_write; int do_server = 0, do_client = 0; + int max_frag = 5 * 1024; - memset(cbuf, 0, sizeof(cbuf)); - memset(sbuf, 0, sizeof(sbuf)); + bufsiz = count > 40 * 1024 ? 40 * 1024 : count; + + if ((cbuf = OPENSSL_malloc(bufsiz)) == NULL) + goto err; + if ((sbuf = OPENSSL_malloc(bufsiz)) == NULL) + goto err; + + memset(cbuf, 0, bufsiz); + memset(sbuf, 0, bufsiz); c_to_s = BIO_new(BIO_s_mem()); s_to_c = BIO_new(BIO_s_mem()); @@ -1541,10 +2041,12 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) SSL_set_connect_state(c_ssl); SSL_set_bio(c_ssl, s_to_c, c_to_s); + SSL_set_max_send_fragment(c_ssl, max_frag); BIO_set_ssl(c_bio, c_ssl, BIO_NOCLOSE); SSL_set_accept_state(s_ssl); SSL_set_bio(s_ssl, c_to_s, s_to_c); + SSL_set_max_send_fragment(s_ssl, max_frag); BIO_set_ssl(s_bio, s_ssl, BIO_NOCLOSE); c_r = 0; @@ -1595,8 +2097,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) } if (do_client && !(done & C_DONE)) { if (c_write) { - j = (cw_num > (long)sizeof(cbuf)) ? - (int)sizeof(cbuf) : (int)cw_num; + j = (cw_num > bufsiz) ? (int)bufsiz : (int)cw_num; i = BIO_write(c_bio, cbuf, j); if (i < 0) { c_r = 0; @@ -1621,9 +2122,11 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) s_r = 1; c_write = 0; cw_num -= i; + if (max_frag > 1029) + SSL_set_max_send_fragment(c_ssl, max_frag -= 5); } } else { - i = BIO_read(c_bio, cbuf, sizeof(cbuf)); + i = BIO_read(c_bio, cbuf, bufsiz); if (i < 0) { c_r = 0; c_w = 0; @@ -1659,7 +2162,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) if (do_server && !(done & S_DONE)) { if (!s_write) { - i = BIO_read(s_bio, sbuf, sizeof(cbuf)); + i = BIO_read(s_bio, sbuf, bufsiz); if (i < 0) { s_r = 0; s_w = 0; @@ -1693,8 +2196,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) } } } else { - j = (sw_num > (long)sizeof(sbuf)) ? - (int)sizeof(sbuf) : (int)sw_num; + j = (sw_num > bufsiz) ? (int)bufsiz : (int)sw_num; i = BIO_write(s_bio, sbuf, j); if (i < 0) { s_r = 0; @@ -1722,6 +2224,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) c_r = 1; if (sw_num <= 0) done |= S_DONE; + if (max_frag > 1029) + SSL_set_max_send_fragment(s_ssl, max_frag -= 5); } } } @@ -1732,6 +2236,14 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) if (verbose) print_details(c_ssl, "DONE: "); + if (verify_serverinfo() < 0) { + ret = 1; + goto err; + } + if (custom_ext_error) { + ret = 1; + goto err; + } ret = 0; err: /* @@ -1759,6 +2271,12 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) BIO_free_all(c_bio); if (s_bio != NULL) BIO_free_all(s_bio); + + if (cbuf) + OPENSSL_free(cbuf); + if (sbuf) + OPENSSL_free(sbuf); + return (ret); } diff --git a/ssl/t1_clnt.c b/ssl/t1_clnt.c index 05c7f200f30f..746b4e6b7a4b 100644 --- a/ssl/t1_clnt.c +++ b/ssl/t1_clnt.c @@ -77,12 +77,14 @@ static const SSL_METHOD *tls1_get_client_method(int ver) IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_client_method, ssl_undefined_function, - ssl3_connect, tls1_get_client_method) + ssl3_connect, + tls1_get_client_method, TLSv1_2_enc_data) IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_client_method, ssl_undefined_function, - ssl3_connect, tls1_get_client_method) + ssl3_connect, + tls1_get_client_method, TLSv1_1_enc_data) IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_client_method, ssl_undefined_function, - ssl3_connect, tls1_get_client_method) + ssl3_connect, tls1_get_client_method, TLSv1_enc_data) diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 8f45294e5579..e2a8f8691978 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -160,7 +160,7 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, { int chunk; size_t j; - EVP_MD_CTX ctx, ctx_tmp; + EVP_MD_CTX ctx, ctx_tmp, ctx_init; EVP_PKEY *mac_key; unsigned char A1[EVP_MAX_MD_SIZE]; size_t A1_len; @@ -171,14 +171,14 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, EVP_MD_CTX_init(&ctx); EVP_MD_CTX_init(&ctx_tmp); - EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - EVP_MD_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + EVP_MD_CTX_init(&ctx_init); + EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); if (!mac_key) goto err; - if (!EVP_DigestSignInit(&ctx, NULL, md, NULL, mac_key)) + if (!EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key)) goto err; - if (!EVP_DigestSignInit(&ctx_tmp, NULL, md, NULL, mac_key)) + if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) goto err; if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) goto err; @@ -195,13 +195,11 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, for (;;) { /* Reinit mac contexts */ - if (!EVP_DigestSignInit(&ctx, NULL, md, NULL, mac_key)) - goto err; - if (!EVP_DigestSignInit(&ctx_tmp, NULL, md, NULL, mac_key)) + if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) goto err; if (!EVP_DigestSignUpdate(&ctx, A1, A1_len)) goto err; - if (!EVP_DigestSignUpdate(&ctx_tmp, A1, A1_len)) + if (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx)) goto err; if (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) goto err; @@ -235,6 +233,7 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, EVP_PKEY_free(mac_key); EVP_MD_CTX_cleanup(&ctx); EVP_MD_CTX_cleanup(&ctx_tmp); + EVP_MD_CTX_cleanup(&ctx_init); OPENSSL_cleanse(A1, sizeof(A1)); return ret; } @@ -405,9 +404,9 @@ int tls1_change_cipher_state(SSL *s, int which) } #endif /* - * this is done by dtls1_reset_seq_numbers for DTLS1_VERSION + * this is done by dtls1_reset_seq_numbers for DTLS */ - if (s->version != DTLS1_VERSION) + if (!SSL_IS_DTLS(s)) memset(&(s->s3->read_sequence[0]), 0, 8); mac_secret = &(s->s3->read_mac_secret[0]); mac_secret_size = &(s->s3->read_mac_secret_size); @@ -443,9 +442,9 @@ int tls1_change_cipher_state(SSL *s, int which) } #endif /* - * this is done by dtls1_reset_seq_numbers for DTLS1_VERSION + * this is done by dtls1_reset_seq_numbers for DTLS */ - if (s->version != DTLS1_VERSION) + if (!SSL_IS_DTLS(s)) memset(&(s->s3->write_sequence[0]), 0, 8); mac_secret = &(s->s3->write_mac_secret[0]); mac_secret_size = &(s->s3->write_mac_secret_size); @@ -574,6 +573,25 @@ int tls1_change_cipher_state(SSL *s, int which) SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err2; } +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) { + int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0; + if (*mac_secret_size) + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC, + mac_secret, *mac_secret_size, + s, s->msg_callback_arg); + if (c->key_len) + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, + key, c->key_len, s, s->msg_callback_arg); + if (k) { + if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) + wh |= TLS1_RT_CRYPTO_FIXED_IV; + else + wh |= TLS1_RT_CRYPTO_IV; + s->msg_callback(2, s->version, wh, iv, k, s, s->msg_callback_arg); + } + } +#endif #ifdef TLS_DEBUG printf("which = %04X\nkey=", which); @@ -741,7 +759,7 @@ int tls1_enc(SSL *s, int send) int ivlen; enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); /* For TLSv1.1 and later explicit IV */ - if (s->version >= TLS1_1_VERSION + if (SSL_USE_EXPLICIT_IV(s) && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) ivlen = EVP_CIPHER_iv_length(enc); else @@ -789,7 +807,7 @@ int tls1_enc(SSL *s, int send) seq = send ? s->s3->write_sequence : s->s3->read_sequence; - if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { unsigned char dtlsseq[9], *p = dtlsseq; s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p); @@ -1010,7 +1028,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) mac_ctx = &hmac; } - if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(ssl)) { unsigned char dtlsseq[8], *p = dtlsseq; s2n(send ? ssl->d1->w_epoch : ssl->d1->r_epoch, p); @@ -1078,7 +1096,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) } #endif - if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER) { + if (!SSL_IS_DTLS(ssl)) { for (i = 7; i >= 0; i--) { ++seq[i]; if (seq[i] != 0) @@ -1144,6 +1162,22 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, SSL3_MASTER_SECRET_SIZE); #endif +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) { + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_PREMASTER, + p, len, s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_CLIENT_RANDOM, + s->s3->client_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_SERVER_RANDOM, + s->s3->server_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_MASTER, + s->session->master_key, + SSL3_MASTER_SECRET_SIZE, s, s->msg_callback_arg); + } +#endif + #ifdef KSSL_DEBUG fprintf(stderr, "tls1_generate_master_secret() complete\n"); #endif /* KSSL_DEBUG */ diff --git a/ssl/t1_ext.c b/ssl/t1_ext.c new file mode 100644 index 000000000000..724ddf76acb3 --- /dev/null +++ b/ssl/t1_ext.c @@ -0,0 +1,298 @@ +/* ssl/t1_ext.c */ +/* ==================================================================== + * Copyright (c) 2014 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Custom extension utility functions */ + +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_TLSEXT + +/* Find a custom extension from the list. */ +static custom_ext_method *custom_ext_find(custom_ext_methods *exts, + unsigned int ext_type) +{ + size_t i; + custom_ext_method *meth = exts->meths; + for (i = 0; i < exts->meths_count; i++, meth++) { + if (ext_type == meth->ext_type) + return meth; + } + return NULL; +} + +/* + * Initialise custom extensions flags to indicate neither sent nor received. + */ +void custom_ext_init(custom_ext_methods *exts) +{ + size_t i; + custom_ext_method *meth = exts->meths; + for (i = 0; i < exts->meths_count; i++, meth++) + meth->ext_flags = 0; +} + +/* Pass received custom extension data to the application for parsing. */ +int custom_ext_parse(SSL *s, int server, + unsigned int ext_type, + const unsigned char *ext_data, size_t ext_size, int *al) +{ + custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; + custom_ext_method *meth; + meth = custom_ext_find(exts, ext_type); + /* If not found return success */ + if (!meth) + return 1; + if (!server) { + /* + * If it's ServerHello we can't have any extensions not sent in + * ClientHello. + */ + if (!(meth->ext_flags & SSL_EXT_FLAG_SENT)) { + *al = TLS1_AD_UNSUPPORTED_EXTENSION; + return 0; + } + } + /* If already present it's a duplicate */ + if (meth->ext_flags & SSL_EXT_FLAG_RECEIVED) { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + meth->ext_flags |= SSL_EXT_FLAG_RECEIVED; + /* If no parse function set return success */ + if (!meth->parse_cb) + return 1; + + return meth->parse_cb(s, ext_type, ext_data, ext_size, al, + meth->parse_arg); +} + +/* + * Request custom extension data from the application and add to the return + * buffer. + */ +int custom_ext_add(SSL *s, int server, + unsigned char **pret, unsigned char *limit, int *al) +{ + custom_ext_methods *exts = server ? &s->cert->srv_ext : &s->cert->cli_ext; + custom_ext_method *meth; + unsigned char *ret = *pret; + size_t i; + + for (i = 0; i < exts->meths_count; i++) { + const unsigned char *out = NULL; + size_t outlen = 0; + meth = exts->meths + i; + + if (server) { + /* + * For ServerHello only send extensions present in ClientHello. + */ + if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED)) + continue; + /* If callback absent for server skip it */ + if (!meth->add_cb) + continue; + } + if (meth->add_cb) { + int cb_retval = 0; + cb_retval = meth->add_cb(s, meth->ext_type, + &out, &outlen, al, meth->add_arg); + if (cb_retval < 0) + return 0; /* error */ + if (cb_retval == 0) + continue; /* skip this extension */ + } + if (4 > limit - ret || outlen > (size_t)(limit - ret - 4)) + return 0; + s2n(meth->ext_type, ret); + s2n(outlen, ret); + if (outlen) { + memcpy(ret, out, outlen); + ret += outlen; + } + /* + * We can't send duplicates: code logic should prevent this. + */ + OPENSSL_assert(!(meth->ext_flags & SSL_EXT_FLAG_SENT)); + /* + * Indicate extension has been sent: this is both a sanity check to + * ensure we don't send duplicate extensions and indicates that it is + * not an error if the extension is present in ServerHello. + */ + meth->ext_flags |= SSL_EXT_FLAG_SENT; + if (meth->free_cb) + meth->free_cb(s, meth->ext_type, out, meth->add_arg); + } + *pret = ret; + return 1; +} + +/* Copy table of custom extensions */ +int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src) +{ + if (src->meths_count) { + dst->meths = + BUF_memdup(src->meths, + sizeof(custom_ext_method) * src->meths_count); + if (dst->meths == NULL) + return 0; + dst->meths_count = src->meths_count; + } + return 1; +} + +void custom_exts_free(custom_ext_methods *exts) +{ + if (exts->meths) + OPENSSL_free(exts->meths); +} + +/* Set callbacks for a custom extension. */ +static int custom_ext_meth_add(custom_ext_methods *exts, + unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, void *parse_arg) +{ + custom_ext_method *meth; + /* + * Check application error: if add_cb is not set free_cb will never be + * called. + */ + if (!add_cb && free_cb) + return 0; + /* Don't add if extension supported internally. */ + if (SSL_extension_supported(ext_type)) + return 0; + /* Extension type must fit in 16 bits */ + if (ext_type > 0xffff) + return 0; + /* Search for duplicate */ + if (custom_ext_find(exts, ext_type)) + return 0; + exts->meths = OPENSSL_realloc(exts->meths, + (exts->meths_count + + 1) * sizeof(custom_ext_method)); + + if (!exts->meths) { + exts->meths_count = 0; + return 0; + } + + meth = exts->meths + exts->meths_count; + memset(meth, 0, sizeof(custom_ext_method)); + meth->parse_cb = parse_cb; + meth->add_cb = add_cb; + meth->free_cb = free_cb; + meth->ext_type = ext_type; + meth->add_arg = add_arg; + meth->parse_arg = parse_arg; + exts->meths_count++; + return 1; +} + +/* Application level functions to add custom extension callbacks */ +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg) +{ + return custom_ext_meth_add(&ctx->cert->cli_ext, ext_type, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg) +{ + return custom_ext_meth_add(&ctx->cert->srv_ext, ext_type, + add_cb, free_cb, add_arg, parse_cb, parse_arg); +} + +int SSL_extension_supported(unsigned int ext_type) +{ + switch (ext_type) { + /* Internally supported extensions. */ + case TLSEXT_TYPE_application_layer_protocol_negotiation: + case TLSEXT_TYPE_ec_point_formats: + case TLSEXT_TYPE_elliptic_curves: + case TLSEXT_TYPE_heartbeat: + case TLSEXT_TYPE_next_proto_neg: + case TLSEXT_TYPE_padding: + case TLSEXT_TYPE_renegotiate: + case TLSEXT_TYPE_server_name: + case TLSEXT_TYPE_session_ticket: + case TLSEXT_TYPE_signature_algorithms: + case TLSEXT_TYPE_srp: + case TLSEXT_TYPE_status_request: + case TLSEXT_TYPE_use_srtp: +# ifdef TLSEXT_TYPE_opaque_prf_input + case TLSEXT_TYPE_opaque_prf_input: +# endif +# ifdef TLSEXT_TYPE_encrypt_then_mac + case TLSEXT_TYPE_encrypt_then_mac: +# endif + return 1; + default: + return 0; + } +} +#endif diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index d70b93feadf0..210a5e87430f 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -113,6 +113,11 @@ #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/hmac.h> +#ifndef OPENSSL_NO_EC +#ifdef OPENSSL_NO_EC2M +# include <openssl/ec.h> +#endif +#endif #include <openssl/ocsp.h> #include <openssl/rand.h> #include "ssl_locl.h" @@ -123,6 +128,8 @@ const char tls1_version_str[] = "TLSv1" OPENSSL_VERSION_PTEXT; static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess); +static int ssl_check_clienthello_tlsext_early(SSL *s); +int ssl_check_serverhello_tlsext(SSL *s); #endif SSL3_ENC_METHOD TLSv1_enc_data = { @@ -138,6 +145,49 @@ SSL3_ENC_METHOD TLSv1_enc_data = { TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write +}; + +SSL3_ENC_METHOD TLSv1_1_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write +}; + +SSL3_ENC_METHOD TLSv1_2_enc_data = { + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF + | SSL_ENC_FLAG_TLS1_2_CIPHERS, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write }; long tls1_default_timeout(void) @@ -200,52 +250,133 @@ static int nid_list[] = { NID_secp256k1, /* secp256k1 (22) */ NID_X9_62_prime256v1, /* secp256r1 (23) */ NID_secp384r1, /* secp384r1 (24) */ - NID_secp521r1 /* secp521r1 (25) */ + NID_secp521r1, /* secp521r1 (25) */ + NID_brainpoolP256r1, /* brainpoolP256r1 (26) */ + NID_brainpoolP384r1, /* brainpoolP384r1 (27) */ + NID_brainpoolP512r1 /* brainpool512r1 (28) */ }; -static int pref_list[] = { -# ifndef OPENSSL_NO_EC2M - NID_sect571r1, /* sect571r1 (14) */ - NID_sect571k1, /* sect571k1 (13) */ -# endif - NID_secp521r1, /* secp521r1 (25) */ -# ifndef OPENSSL_NO_EC2M - NID_sect409k1, /* sect409k1 (11) */ - NID_sect409r1, /* sect409r1 (12) */ -# endif - NID_secp384r1, /* secp384r1 (24) */ -# ifndef OPENSSL_NO_EC2M - NID_sect283k1, /* sect283k1 (9) */ - NID_sect283r1, /* sect283r1 (10) */ -# endif - NID_secp256k1, /* secp256k1 (22) */ - NID_X9_62_prime256v1, /* secp256r1 (23) */ +static const unsigned char ecformats_default[] = { + TLSEXT_ECPOINTFORMAT_uncompressed, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 +}; + +/* The client's default curves / the server's 'auto' curves. */ +static const unsigned char eccurves_auto[] = { + /* Prefer P-256 which has the fastest and most secure implementations. */ + 0, 23, /* secp256r1 (23) */ + /* Other >= 256-bit prime curves. */ + 0, 25, /* secp521r1 (25) */ + 0, 28, /* brainpool512r1 (28) */ + 0, 27, /* brainpoolP384r1 (27) */ + 0, 24, /* secp384r1 (24) */ + 0, 26, /* brainpoolP256r1 (26) */ + 0, 22, /* secp256k1 (22) */ # ifndef OPENSSL_NO_EC2M - NID_sect239k1, /* sect239k1 (8) */ - NID_sect233k1, /* sect233k1 (6) */ - NID_sect233r1, /* sect233r1 (7) */ + /* >= 256-bit binary curves. */ + 0, 14, /* sect571r1 (14) */ + 0, 13, /* sect571k1 (13) */ + 0, 11, /* sect409k1 (11) */ + 0, 12, /* sect409r1 (12) */ + 0, 9, /* sect283k1 (9) */ + 0, 10, /* sect283r1 (10) */ # endif - NID_secp224k1, /* secp224k1 (20) */ - NID_secp224r1, /* secp224r1 (21) */ +}; + +static const unsigned char eccurves_all[] = { + /* Prefer P-256 which has the fastest and most secure implementations. */ + 0, 23, /* secp256r1 (23) */ + /* Other >= 256-bit prime curves. */ + 0, 25, /* secp521r1 (25) */ + 0, 28, /* brainpool512r1 (28) */ + 0, 27, /* brainpoolP384r1 (27) */ + 0, 24, /* secp384r1 (24) */ + 0, 26, /* brainpoolP256r1 (26) */ + 0, 22, /* secp256k1 (22) */ # ifndef OPENSSL_NO_EC2M - NID_sect193r1, /* sect193r1 (4) */ - NID_sect193r2, /* sect193r2 (5) */ + /* >= 256-bit binary curves. */ + 0, 14, /* sect571r1 (14) */ + 0, 13, /* sect571k1 (13) */ + 0, 11, /* sect409k1 (11) */ + 0, 12, /* sect409r1 (12) */ + 0, 9, /* sect283k1 (9) */ + 0, 10, /* sect283r1 (10) */ # endif - NID_secp192k1, /* secp192k1 (18) */ - NID_X9_62_prime192v1, /* secp192r1 (19) */ + /* + * Remaining curves disabled by default but still permitted if set + * via an explicit callback or parameters. + */ + 0, 20, /* secp224k1 (20) */ + 0, 21, /* secp224r1 (21) */ + 0, 18, /* secp192k1 (18) */ + 0, 19, /* secp192r1 (19) */ + 0, 15, /* secp160k1 (15) */ + 0, 16, /* secp160r1 (16) */ + 0, 17, /* secp160r2 (17) */ # ifndef OPENSSL_NO_EC2M - NID_sect163k1, /* sect163k1 (1) */ - NID_sect163r1, /* sect163r1 (2) */ - NID_sect163r2, /* sect163r2 (3) */ + 0, 8, /* sect239k1 (8) */ + 0, 6, /* sect233k1 (6) */ + 0, 7, /* sect233r1 (7) */ + 0, 4, /* sect193r1 (4) */ + 0, 5, /* sect193r2 (5) */ + 0, 1, /* sect163k1 (1) */ + 0, 2, /* sect163r1 (2) */ + 0, 3, /* sect163r2 (3) */ # endif - NID_secp160k1, /* secp160k1 (15) */ - NID_secp160r1, /* secp160r1 (16) */ - NID_secp160r2, /* secp160r2 (17) */ }; +static const unsigned char suiteb_curves[] = { + 0, TLSEXT_curve_P_256, + 0, TLSEXT_curve_P_384 +}; + +# ifdef OPENSSL_FIPS +/* Brainpool not allowed in FIPS mode */ +static const unsigned char fips_curves_default[] = { +# ifndef OPENSSL_NO_EC2M + 0, 14, /* sect571r1 (14) */ + 0, 13, /* sect571k1 (13) */ +# endif + 0, 25, /* secp521r1 (25) */ +# ifndef OPENSSL_NO_EC2M + 0, 11, /* sect409k1 (11) */ + 0, 12, /* sect409r1 (12) */ +# endif + 0, 24, /* secp384r1 (24) */ +# ifndef OPENSSL_NO_EC2M + 0, 9, /* sect283k1 (9) */ + 0, 10, /* sect283r1 (10) */ +# endif + 0, 22, /* secp256k1 (22) */ + 0, 23, /* secp256r1 (23) */ +# ifndef OPENSSL_NO_EC2M + 0, 8, /* sect239k1 (8) */ + 0, 6, /* sect233k1 (6) */ + 0, 7, /* sect233r1 (7) */ +# endif + 0, 20, /* secp224k1 (20) */ + 0, 21, /* secp224r1 (21) */ +# ifndef OPENSSL_NO_EC2M + 0, 4, /* sect193r1 (4) */ + 0, 5, /* sect193r2 (5) */ +# endif + 0, 18, /* secp192k1 (18) */ + 0, 19, /* secp192r1 (19) */ +# ifndef OPENSSL_NO_EC2M + 0, 1, /* sect163k1 (1) */ + 0, 2, /* sect163r1 (2) */ + 0, 3, /* sect163r2 (3) */ +# endif + 0, 15, /* secp160k1 (15) */ + 0, 16, /* secp160r1 (16) */ + 0, 17, /* secp160r2 (17) */ +}; +# endif + int tls1_ec_curve_id2nid(int curve_id) { - /* ECC curves from RFC 4492 */ + /* ECC curves from RFC 4492 and RFC 7027 */ if ((curve_id < 1) || ((unsigned int)curve_id > sizeof(nid_list) / sizeof(nid_list[0]))) return 0; @@ -254,7 +385,7 @@ int tls1_ec_curve_id2nid(int curve_id) int tls1_ec_nid2curve_id(int nid) { - /* ECC curves from RFC 4492 */ + /* ECC curves from RFC 4492 and RFC 7027 */ switch (nid) { case NID_sect163k1: /* sect163k1 (1) */ return 1; @@ -306,10 +437,548 @@ int tls1_ec_nid2curve_id(int nid) return 24; case NID_secp521r1: /* secp521r1 (25) */ return 25; + case NID_brainpoolP256r1: /* brainpoolP256r1 (26) */ + return 26; + case NID_brainpoolP384r1: /* brainpoolP384r1 (27) */ + return 27; + case NID_brainpoolP512r1: /* brainpool512r1 (28) */ + return 28; default: return 0; } } + +/* + * Get curves list, if "sess" is set return client curves otherwise + * preferred list. + * Sets |num_curves| to the number of curves in the list, i.e., + * the length of |pcurves| is 2 * num_curves. + * Returns 1 on success and 0 if the client curves list has invalid format. + * The latter indicates an internal error: we should not be accepting such + * lists in the first place. + * TODO(emilia): we should really be storing the curves list in explicitly + * parsed form instead. (However, this would affect binary compatibility + * so cannot happen in the 1.0.x series.) + */ +static int tls1_get_curvelist(SSL *s, int sess, + const unsigned char **pcurves, + size_t *num_curves) +{ + size_t pcurveslen = 0; + if (sess) { + *pcurves = s->session->tlsext_ellipticcurvelist; + pcurveslen = s->session->tlsext_ellipticcurvelist_length; + } else { + /* For Suite B mode only include P-256, P-384 */ + switch (tls1_suiteb(s)) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + *pcurves = suiteb_curves; + pcurveslen = sizeof(suiteb_curves); + break; + + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *pcurves = suiteb_curves; + pcurveslen = 2; + break; + + case SSL_CERT_FLAG_SUITEB_192_LOS: + *pcurves = suiteb_curves + 2; + pcurveslen = 2; + break; + default: + *pcurves = s->tlsext_ellipticcurvelist; + pcurveslen = s->tlsext_ellipticcurvelist_length; + } + if (!*pcurves) { +# ifdef OPENSSL_FIPS + if (FIPS_mode()) { + *pcurves = fips_curves_default; + pcurveslen = sizeof(fips_curves_default); + } else +# endif + { + if (!s->server || (s->cert && s->cert->ecdh_tmp_auto)) { + *pcurves = eccurves_auto; + pcurveslen = sizeof(eccurves_auto); + } else { + *pcurves = eccurves_all; + pcurveslen = sizeof(eccurves_all); + } + } + } + } + /* We do not allow odd length arrays to enter the system. */ + if (pcurveslen & 1) { + SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR); + *num_curves = 0; + return 0; + } else { + *num_curves = pcurveslen / 2; + return 1; + } +} + +/* Check a curve is one of our preferences */ +int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) +{ + const unsigned char *curves; + size_t num_curves, i; + unsigned int suiteb_flags = tls1_suiteb(s); + if (len != 3 || p[0] != NAMED_CURVE_TYPE) + return 0; + /* Check curve matches Suite B preferences */ + if (suiteb_flags) { + unsigned long cid = s->s3->tmp.new_cipher->id; + if (p[1]) + return 0; + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) { + if (p[2] != TLSEXT_curve_P_256) + return 0; + } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) { + if (p[2] != TLSEXT_curve_P_384) + return 0; + } else /* Should never happen */ + return 0; + } + if (!tls1_get_curvelist(s, 0, &curves, &num_curves)) + return 0; + for (i = 0; i < num_curves; i++, curves += 2) { + if (p[1] == curves[0] && p[2] == curves[1]) + return 1; + } + return 0; +} + +/*- + * Return |nmatch|th shared curve or NID_undef if there is no match. + * For nmatch == -1, return number of matches + * For nmatch == -2, return the NID of the curve to use for + * an EC tmp key, or NID_undef if there is no match. + */ +int tls1_shared_curve(SSL *s, int nmatch) +{ + const unsigned char *pref, *supp; + size_t num_pref, num_supp, i, j; + int k; + /* Can't do anything on client side */ + if (s->server == 0) + return -1; + if (nmatch == -2) { + if (tls1_suiteb(s)) { + /* + * For Suite B ciphersuite determines curve: we already know + * these are acceptable due to previous checks. + */ + unsigned long cid = s->s3->tmp.new_cipher->id; + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + return NID_X9_62_prime256v1; /* P-256 */ + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + return NID_secp384r1; /* P-384 */ + /* Should never happen */ + return NID_undef; + } + /* If not Suite B just return first preference shared curve */ + nmatch = 0; + } + /* + * Avoid truncation. tls1_get_curvelist takes an int + * but s->options is a long... + */ + if (!tls1_get_curvelist + (s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0, &supp, + &num_supp)) + /* In practice, NID_undef == 0 but let's be precise. */ + return nmatch == -1 ? 0 : NID_undef; + if (!tls1_get_curvelist + (s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref, + &num_pref)) + return nmatch == -1 ? 0 : NID_undef; + + /* + * If the client didn't send the elliptic_curves extension all of them + * are allowed. + */ + if (num_supp == 0 && (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0) { + supp = eccurves_all; + num_supp = sizeof(eccurves_all) / 2; + } else if (num_pref == 0 && + (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0) { + pref = eccurves_all; + num_pref = sizeof(eccurves_all) / 2; + } + + k = 0; + for (i = 0; i < num_pref; i++, pref += 2) { + const unsigned char *tsupp = supp; + for (j = 0; j < num_supp; j++, tsupp += 2) { + if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) { + if (nmatch == k) { + int id = (pref[0] << 8) | pref[1]; + return tls1_ec_curve_id2nid(id); + } + k++; + } + } + } + if (nmatch == -1) + return k; + /* Out of range (nmatch > k). */ + return NID_undef; +} + +int tls1_set_curves(unsigned char **pext, size_t *pextlen, + int *curves, size_t ncurves) +{ + unsigned char *clist, *p; + size_t i; + /* + * Bitmap of curves included to detect duplicates: only works while curve + * ids < 32 + */ + unsigned long dup_list = 0; +# ifdef OPENSSL_NO_EC2M + EC_GROUP *curve; +# endif + + clist = OPENSSL_malloc(ncurves * 2); + if (!clist) + return 0; + for (i = 0, p = clist; i < ncurves; i++) { + unsigned long idmask; + int id; + id = tls1_ec_nid2curve_id(curves[i]); +# ifdef OPENSSL_FIPS + /* NB: 25 is last curve ID supported by FIPS module */ + if (FIPS_mode() && id > 25) { + OPENSSL_free(clist); + return 0; + } +# endif +# ifdef OPENSSL_NO_EC2M + curve = EC_GROUP_new_by_curve_name(curves[i]); + if (!curve || EC_METHOD_get_field_type(EC_GROUP_method_of(curve)) + == NID_X9_62_characteristic_two_field) { + if (curve) + EC_GROUP_free(curve); + OPENSSL_free(clist); + return 0; + } else + EC_GROUP_free(curve); +# endif + idmask = 1L << id; + if (!id || (dup_list & idmask)) { + OPENSSL_free(clist); + return 0; + } + dup_list |= idmask; + s2n(id, p); + } + if (*pext) + OPENSSL_free(*pext); + *pext = clist; + *pextlen = ncurves * 2; + return 1; +} + +# define MAX_CURVELIST 28 + +typedef struct { + size_t nidcnt; + int nid_arr[MAX_CURVELIST]; +} nid_cb_st; + +static int nid_cb(const char *elem, int len, void *arg) +{ + nid_cb_st *narg = arg; + size_t i; + int nid; + char etmp[20]; + if (elem == NULL) + return 0; + if (narg->nidcnt == MAX_CURVELIST) + return 0; + if (len > (int)(sizeof(etmp) - 1)) + return 0; + memcpy(etmp, elem, len); + etmp[len] = 0; + nid = EC_curve_nist2nid(etmp); + if (nid == NID_undef) + nid = OBJ_sn2nid(etmp); + if (nid == NID_undef) + nid = OBJ_ln2nid(etmp); + if (nid == NID_undef) + return 0; + for (i = 0; i < narg->nidcnt; i++) + if (narg->nid_arr[i] == nid) + return 0; + narg->nid_arr[narg->nidcnt++] = nid; + return 1; +} + +/* Set curves based on a colon separate list */ +int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, + const char *str) +{ + nid_cb_st ncb; + ncb.nidcnt = 0; + if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb)) + return 0; + if (pext == NULL) + return 1; + return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt); +} + +/* For an EC key set TLS id and required compression based on parameters */ +static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, + EC_KEY *ec) +{ + int is_prime, id; + const EC_GROUP *grp; + const EC_METHOD *meth; + if (!ec) + return 0; + /* Determine if it is a prime field */ + grp = EC_KEY_get0_group(ec); + if (!grp) + return 0; + meth = EC_GROUP_method_of(grp); + if (!meth) + return 0; + if (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field) + is_prime = 1; + else + is_prime = 0; + /* Determine curve ID */ + id = EC_GROUP_get_curve_name(grp); + id = tls1_ec_nid2curve_id(id); + /* If we have an ID set it, otherwise set arbitrary explicit curve */ + if (id) { + curve_id[0] = 0; + curve_id[1] = (unsigned char)id; + } else { + curve_id[0] = 0xff; + if (is_prime) + curve_id[1] = 0x01; + else + curve_id[1] = 0x02; + } + if (comp_id) { + if (EC_KEY_get0_public_key(ec) == NULL) + return 0; + if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { + if (is_prime) + *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + else + *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + } else + *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + } + return 1; +} + +/* Check an EC key is compatible with extensions */ +static int tls1_check_ec_key(SSL *s, + unsigned char *curve_id, unsigned char *comp_id) +{ + const unsigned char *pformats, *pcurves; + size_t num_formats, num_curves, i; + int j; + /* + * If point formats extension present check it, otherwise everything is + * supported (see RFC4492). + */ + if (comp_id && s->session->tlsext_ecpointformatlist) { + pformats = s->session->tlsext_ecpointformatlist; + num_formats = s->session->tlsext_ecpointformatlist_length; + for (i = 0; i < num_formats; i++, pformats++) { + if (*comp_id == *pformats) + break; + } + if (i == num_formats) + return 0; + } + if (!curve_id) + return 1; + /* Check curve is consistent with client and server preferences */ + for (j = 0; j <= 1; j++) { + if (!tls1_get_curvelist(s, j, &pcurves, &num_curves)) + return 0; + if (j == 1 && num_curves == 0) { + /* + * If we've not received any curves then skip this check. + * RFC 4492 does not require the supported elliptic curves extension + * so if it is not sent we can just choose any curve. + * It is invalid to send an empty list in the elliptic curves + * extension, so num_curves == 0 always means no extension. + */ + break; + } + for (i = 0; i < num_curves; i++, pcurves += 2) { + if (pcurves[0] == curve_id[0] && pcurves[1] == curve_id[1]) + break; + } + if (i == num_curves) + return 0; + /* For clients can only check sent curve list */ + if (!s->server) + return 1; + } + return 1; +} + +static void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + size_t *num_formats) +{ + /* + * If we have a custom point format list use it otherwise use default + */ + if (s->tlsext_ecpointformatlist) { + *pformats = s->tlsext_ecpointformatlist; + *num_formats = s->tlsext_ecpointformatlist_length; + } else { + *pformats = ecformats_default; + /* For Suite B we don't support char2 fields */ + if (tls1_suiteb(s)) + *num_formats = sizeof(ecformats_default) - 1; + else + *num_formats = sizeof(ecformats_default); + } +} + +/* + * Check cert parameters compatible with extensions: currently just checks EC + * certificates have compatible curves and compression. + */ +static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) +{ + unsigned char comp_id, curve_id[2]; + EVP_PKEY *pkey; + int rv; + pkey = X509_get_pubkey(x); + if (!pkey) + return 0; + /* If not EC nothing to do */ + if (pkey->type != EVP_PKEY_EC) { + EVP_PKEY_free(pkey); + return 1; + } + rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec); + EVP_PKEY_free(pkey); + if (!rv) + return 0; + /* + * Can't check curve_id for client certs as we don't have a supported + * curves extension. + */ + rv = tls1_check_ec_key(s, s->server ? curve_id : NULL, &comp_id); + if (!rv) + return 0; + /* + * Special case for suite B. We *MUST* sign using SHA256+P-256 or + * SHA384+P-384, adjust digest if necessary. + */ + if (set_ee_md && tls1_suiteb(s)) { + int check_md; + size_t i; + CERT *c = s->cert; + if (curve_id[0]) + return 0; + /* Check to see we have necessary signing algorithm */ + if (curve_id[1] == TLSEXT_curve_P_256) + check_md = NID_ecdsa_with_SHA256; + else if (curve_id[1] == TLSEXT_curve_P_384) + check_md = NID_ecdsa_with_SHA384; + else + return 0; /* Should never happen */ + for (i = 0; i < c->shared_sigalgslen; i++) + if (check_md == c->shared_sigalgs[i].signandhash_nid) + break; + if (i == c->shared_sigalgslen) + return 0; + if (set_ee_md == 2) { + if (check_md == NID_ecdsa_with_SHA256) + c->pkeys[SSL_PKEY_ECC].digest = EVP_sha256(); + else + c->pkeys[SSL_PKEY_ECC].digest = EVP_sha384(); + } + } + return rv; +} + +# ifndef OPENSSL_NO_ECDH +/* Check EC temporary key is compatible with client extensions */ +int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) +{ + unsigned char curve_id[2]; + EC_KEY *ec = s->cert->ecdh_tmp; +# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* Allow any curve: not just those peer supports */ + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) + return 1; +# endif + /* + * If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other + * curves permitted. + */ + if (tls1_suiteb(s)) { + /* Curve to check determined by ciphersuite */ + if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + curve_id[1] = TLSEXT_curve_P_256; + else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + curve_id[1] = TLSEXT_curve_P_384; + else + return 0; + curve_id[0] = 0; + /* Check this curve is acceptable */ + if (!tls1_check_ec_key(s, curve_id, NULL)) + return 0; + /* If auto or setting curve from callback assume OK */ + if (s->cert->ecdh_tmp_auto || s->cert->ecdh_tmp_cb) + return 1; + /* Otherwise check curve is acceptable */ + else { + unsigned char curve_tmp[2]; + if (!ec) + return 0; + if (!tls1_set_ec_id(curve_tmp, NULL, ec)) + return 0; + if (!curve_tmp[0] || curve_tmp[1] == curve_id[1]) + return 1; + return 0; + } + + } + if (s->cert->ecdh_tmp_auto) { + /* Need a shared curve */ + if (tls1_shared_curve(s, 0)) + return 1; + else + return 0; + } + if (!ec) { + if (s->cert->ecdh_tmp_cb) + return 1; + else + return 0; + } + if (!tls1_set_ec_id(curve_id, NULL, ec)) + return 0; +/* Set this to allow use of invalid curves for testing */ +# if 0 + return 1; +# else + return tls1_check_ec_key(s, curve_id, NULL); +# endif +} +# endif /* OPENSSL_NO_ECDH */ + +#else + +static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) +{ + return 1; +} + #endif /* OPENSSL_NO_EC */ #ifndef OPENSSL_NO_TLSEXT @@ -357,20 +1026,231 @@ static unsigned char tls12_sigalgs[] = { # endif }; -int tls12_get_req_sig_algs(SSL *s, unsigned char *p) +# ifndef OPENSSL_NO_ECDSA +static unsigned char suiteb_sigalgs[] = { + tlsext_sigalg_ecdsa(TLSEXT_hash_sha256) + tlsext_sigalg_ecdsa(TLSEXT_hash_sha384) +}; +# endif +size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) { - size_t slen = sizeof(tls12_sigalgs); - if (p) - memcpy(p, tls12_sigalgs, slen); - return (int)slen; + /* + * If Suite B mode use Suite B sigalgs only, ignore any other + * preferences. + */ +# ifndef OPENSSL_NO_EC + switch (tls1_suiteb(s)) { + case SSL_CERT_FLAG_SUITEB_128_LOS: + *psigs = suiteb_sigalgs; + return sizeof(suiteb_sigalgs); + + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *psigs = suiteb_sigalgs; + return 2; + + case SSL_CERT_FLAG_SUITEB_192_LOS: + *psigs = suiteb_sigalgs + 2; + return 2; + } +# endif + /* If server use client authentication sigalgs if not NULL */ + if (s->server && s->cert->client_sigalgs) { + *psigs = s->cert->client_sigalgs; + return s->cert->client_sigalgslen; + } else if (s->cert->conf_sigalgs) { + *psigs = s->cert->conf_sigalgs; + return s->cert->conf_sigalgslen; + } else { + *psigs = tls12_sigalgs; + return sizeof(tls12_sigalgs); + } +} + +/* + * Check signature algorithm is consistent with sent supported signature + * algorithms and if so return relevant digest. + */ +int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, + const unsigned char *sig, EVP_PKEY *pkey) +{ + const unsigned char *sent_sigs; + size_t sent_sigslen, i; + int sigalg = tls12_get_sigid(pkey); + /* Should never happen */ + if (sigalg == -1) + return -1; + /* Check key type is consistent with signature */ + if (sigalg != (int)sig[1]) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } +# ifndef OPENSSL_NO_EC + if (pkey->type == EVP_PKEY_EC) { + unsigned char curve_id[2], comp_id; + /* Check compression and curve matches extensions */ + if (!tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec)) + return 0; + if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id)) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE); + return 0; + } + /* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */ + if (tls1_suiteb(s)) { + if (curve_id[0]) + return 0; + if (curve_id[1] == TLSEXT_curve_P_256) { + if (sig[0] != TLSEXT_hash_sha256) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_ILLEGAL_SUITEB_DIGEST); + return 0; + } + } else if (curve_id[1] == TLSEXT_curve_P_384) { + if (sig[0] != TLSEXT_hash_sha384) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, + SSL_R_ILLEGAL_SUITEB_DIGEST); + return 0; + } + } else + return 0; + } + } else if (tls1_suiteb(s)) + return 0; +# endif + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); + for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { + if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1]) + break; + } + /* Allow fallback to SHA1 if not strict mode */ + if (i == sent_sigslen + && (sig[0] != TLSEXT_hash_sha1 + || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } + *pmd = tls12_get_hash(sig[0]); + if (*pmd == NULL) { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST); + return 0; + } + /* + * Store the digest used so applications can retrieve it if they wish. + */ + if (s->session && s->session->sess_cert) + s->session->sess_cert->peer_key->digest = *pmd; + return 1; +} + +/* + * Get a mask of disabled algorithms: an algorithm is disabled if it isn't + * supported or doesn't appear in supported signature algorithms. Unlike + * ssl_cipher_get_disabled this applies to a specific session and not global + * settings. + */ +void ssl_set_client_disabled(SSL *s) +{ + CERT *c = s->cert; + const unsigned char *sigalgs; + size_t i, sigalgslen; + int have_rsa = 0, have_dsa = 0, have_ecdsa = 0; + c->mask_a = 0; + c->mask_k = 0; + /* Don't allow TLS 1.2 only ciphers if we don't suppport them */ + if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) + c->mask_ssl = SSL_TLSV1_2; + else + c->mask_ssl = 0; + /* + * Now go through all signature algorithms seeing if we support any for + * RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2. + */ + sigalgslen = tls12_get_psigalgs(s, &sigalgs); + for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { + switch (sigalgs[1]) { +# ifndef OPENSSL_NO_RSA + case TLSEXT_signature_rsa: + have_rsa = 1; + break; +# endif +# ifndef OPENSSL_NO_DSA + case TLSEXT_signature_dsa: + have_dsa = 1; + break; +# endif +# ifndef OPENSSL_NO_ECDSA + case TLSEXT_signature_ecdsa: + have_ecdsa = 1; + break; +# endif + } + } + /* + * Disable auth and static DH if we don't include any appropriate + * signature algorithms. + */ + if (!have_rsa) { + c->mask_a |= SSL_aRSA; + c->mask_k |= SSL_kDHr | SSL_kECDHr; + } + if (!have_dsa) { + c->mask_a |= SSL_aDSS; + c->mask_k |= SSL_kDHd; + } + if (!have_ecdsa) { + c->mask_a |= SSL_aECDSA; + c->mask_k |= SSL_kECDHe; + } +# ifndef OPENSSL_NO_KRB5 + if (!kssl_tgt_is_available(s->kssl_ctx)) { + c->mask_a |= SSL_aKRB5; + c->mask_k |= SSL_kKRB5; + } +# endif +# ifndef OPENSSL_NO_PSK + /* with PSK there must be client callback set */ + if (!s->psk_client_callback) { + c->mask_a |= SSL_aPSK; + c->mask_k |= SSL_kPSK; + } +# endif /* OPENSSL_NO_PSK */ +# ifndef OPENSSL_NO_SRP + if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) { + c->mask_a |= SSL_aSRP; + c->mask_k |= SSL_kSRP; + } +# endif + c->valid = 1; } unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, - unsigned char *limit) + unsigned char *limit, int *al) { int extdatalen = 0; unsigned char *orig = buf; unsigned char *ret = buf; +# ifndef OPENSSL_NO_EC + /* See if we support any ECC ciphersuites */ + int using_ecc = 0; + if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) { + int i; + unsigned long alg_k, alg_a; + STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); + + for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) { + SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + if ((alg_k & (SSL_kEECDH | SSL_kECDHr | SSL_kECDHe) + || (alg_a & SSL_aECDSA))) { + using_ecc = 1; + break; + } + } + } +# endif /* don't add extensions for SSLv3 unless doing secure renegotiation */ if (s->client_version == SSL3_VERSION && !s->s3->send_connection_binding) @@ -466,50 +1346,53 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, # endif # ifndef OPENSSL_NO_EC - if (s->tlsext_ecpointformatlist != NULL) { + if (using_ecc) { /* * Add TLS extension ECPointFormats to the ClientHello message */ long lenmax; + const unsigned char *pcurves, *pformats; + size_t num_curves, num_formats, curves_list_len; + + tls1_get_formatlist(s, &pformats, &num_formats); if ((lenmax = limit - ret - 5) < 0) return NULL; - if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) + if (num_formats > (size_t)lenmax) return NULL; - if (s->tlsext_ecpointformatlist_length > 255) { + if (num_formats > 255) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } s2n(TLSEXT_TYPE_ec_point_formats, ret); - s2n(s->tlsext_ecpointformatlist_length + 1, ret); - *(ret++) = (unsigned char)s->tlsext_ecpointformatlist_length; - memcpy(ret, s->tlsext_ecpointformatlist, - s->tlsext_ecpointformatlist_length); - ret += s->tlsext_ecpointformatlist_length; - } - if (s->tlsext_ellipticcurvelist != NULL) { + /* The point format list has 1-byte length. */ + s2n(num_formats + 1, ret); + *(ret++) = (unsigned char)num_formats; + memcpy(ret, pformats, num_formats); + ret += num_formats; + /* * Add TLS extension EllipticCurves to the ClientHello message */ - long lenmax; + pcurves = s->tlsext_ellipticcurvelist; + if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) + return NULL; if ((lenmax = limit - ret - 6) < 0) return NULL; - if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) + if (num_curves > (size_t)lenmax / 2) return NULL; - if (s->tlsext_ellipticcurvelist_length > 65532) { + if (num_curves > 65532 / 2) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } - + curves_list_len = 2 * num_curves; s2n(TLSEXT_TYPE_elliptic_curves, ret); - s2n(s->tlsext_ellipticcurvelist_length + 2, ret); - - s2n(s->tlsext_ellipticcurvelist_length, ret); - memcpy(ret, s->tlsext_ellipticcurvelist, - s->tlsext_ellipticcurvelist_length); - ret += s->tlsext_ellipticcurvelist_length; + s2n(curves_list_len + 2, ret); + s2n(curves_list_len, ret); + memcpy(ret, pcurves, curves_list_len); + ret += curves_list_len; } # endif /* OPENSSL_NO_EC */ @@ -546,17 +1429,20 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, } skip_ext: - if (TLS1_get_client_version(s) >= TLS1_2_VERSION) { - if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6) + if (SSL_USE_SIGALGS(s)) { + size_t salglen; + const unsigned char *salg; + salglen = tls12_get_psigalgs(s, &salg); + if ((size_t)(limit - ret) < salglen + 6) return NULL; s2n(TLSEXT_TYPE_signature_algorithms, ret); - s2n(sizeof(tls12_sigalgs) + 2, ret); - s2n(sizeof(tls12_sigalgs), ret); - memcpy(ret, tls12_sigalgs, sizeof(tls12_sigalgs)); - ret += sizeof(tls12_sigalgs); + s2n(salglen + 2, ret); + s2n(salglen, ret); + memcpy(ret, salg, salglen); + ret += salglen; } # ifdef TLSEXT_TYPE_opaque_prf_input - if (s->s3->client_opaque_prf_input != NULL && s->version != DTLS1_VERSION) { + if (s->s3->client_opaque_prf_input != NULL) { size_t col = s->s3->client_opaque_prf_input_len; if ((long)(limit - ret - 6 - col < 0)) @@ -572,8 +1458,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, } # endif - if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && - s->version != DTLS1_VERSION) { + if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { int i; long extlen, idlen, itmp; OCSP_RESPID *id; @@ -646,6 +1531,15 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, } # endif + if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) { + if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) + return NULL; + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); + s2n(2 + s->alpn_client_proto_list_len, ret); + s2n(s->alpn_client_proto_list_len, ret); + memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len); + ret += s->alpn_client_proto_list_len; + } # ifndef OPENSSL_NO_SRTP if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) { int el; @@ -665,6 +1559,11 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, ret += el; } # endif + custom_ext_init(&s->cert->cli_ext); + /* Add custom TLS Extensions to ClientHello */ + if (!custom_ext_add(s, 0, &ret, limit, al)) + return NULL; + /* * Add padding to workaround bugs in F5 terminators. See * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this @@ -702,7 +1601,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, } unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, - unsigned char *limit) + unsigned char *limit, int *al) { int extdatalen = 0; unsigned char *orig = buf; @@ -710,7 +1609,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, # ifndef OPENSSL_NO_NEXTPROTONEG int next_proto_neg_seen; # endif - +# ifndef OPENSSL_NO_EC + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + int using_ecc = (alg_k & (SSL_kEECDH | SSL_kECDHr | SSL_kECDHe)) + || (alg_a & SSL_aECDSA); + using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); +# endif /* * don't add extensions for SSLv3, unless doing secure renegotiation */ @@ -752,27 +1657,30 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, ret += el; } # ifndef OPENSSL_NO_EC - if (s->tlsext_ecpointformatlist != NULL) { + if (using_ecc) { + const unsigned char *plist; + size_t plistlen; /* * Add TLS extension ECPointFormats to the ServerHello message */ long lenmax; + tls1_get_formatlist(s, &plist, &plistlen); + if ((lenmax = limit - ret - 5) < 0) return NULL; - if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) + if (plistlen > (size_t)lenmax) return NULL; - if (s->tlsext_ecpointformatlist_length > 255) { + if (plistlen > 255) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } s2n(TLSEXT_TYPE_ec_point_formats, ret); - s2n(s->tlsext_ecpointformatlist_length + 1, ret); - *(ret++) = (unsigned char)s->tlsext_ecpointformatlist_length; - memcpy(ret, s->tlsext_ecpointformatlist, - s->tlsext_ecpointformatlist_length); - ret += s->tlsext_ecpointformatlist_length; + s2n(plistlen + 1, ret); + *(ret++) = (unsigned char)plistlen; + memcpy(ret, plist, plistlen); + ret += plistlen; } /* @@ -795,7 +1703,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, s2n(0, ret); } # ifdef TLSEXT_TYPE_opaque_prf_input - if (s->s3->server_opaque_prf_input != NULL && s->version != DTLS1_VERSION) { + if (s->s3->server_opaque_prf_input != NULL) { size_t sol = s->s3->server_opaque_prf_input_len; if ((long)(limit - ret - 6 - sol) < 0) @@ -890,6 +1798,22 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, } } # endif + if (!custom_ext_add(s, 1, &ret, limit, al)) + return NULL; + + if (s->s3->alpn_selected) { + const unsigned char *selected = s->s3->alpn_selected; + unsigned len = s->s3->alpn_selected_len; + + if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) + return NULL; + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); + s2n(3 + len, ret); + s2n(1 + len, ret); + *ret++ = len; + memcpy(ret, selected, len); + ret += len; + } if ((extdatalen = ret - orig - 2) == 0) return orig; @@ -981,15 +1905,82 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, } # endif /* !OPENSSL_NO_EC */ -int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, - int n, int *al) +/* + * tls1_alpn_handle_client_hello is called to process the ALPN extension in a + * ClientHello. data: the contents of the extension, not including the type + * and length. data_len: the number of bytes in |data| al: a pointer to the + * alert value to send in the event of a non-zero return. returns: 0 on + * success. + */ +static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data, + unsigned data_len, int *al) +{ + unsigned i; + unsigned proto_len; + const unsigned char *selected; + unsigned char selected_len; + int r; + + if (s->ctx->alpn_select_cb == NULL) + return 0; + + if (data_len < 2) + goto parse_error; + + /* + * data should contain a uint16 length followed by a series of 8-bit, + * length-prefixed strings. + */ + i = ((unsigned)data[0]) << 8 | ((unsigned)data[1]); + data_len -= 2; + data += 2; + if (data_len != i) + goto parse_error; + + if (data_len < 2) + goto parse_error; + + for (i = 0; i < data_len;) { + proto_len = data[i]; + i++; + + if (proto_len == 0) + goto parse_error; + + if (i + proto_len < i || i + proto_len > data_len) + goto parse_error; + + i += proto_len; + } + + r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len, + s->ctx->alpn_select_cb_arg); + if (r == SSL_TLSEXT_ERR_OK) { + if (s->s3->alpn_selected) + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_malloc(selected_len); + if (!s->s3->alpn_selected) { + *al = SSL_AD_INTERNAL_ERROR; + return -1; + } + memcpy(s->s3->alpn_selected, selected, selected_len); + s->s3->alpn_selected_len = selected_len; + } + return 0; + + parse_error: + *al = SSL_AD_DECODE_ERROR; + return -1; +} + +static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, + unsigned char *d, int n, int *al) { unsigned short type; unsigned short size; unsigned short len; unsigned char *data = *p; int renegotiate_seen = 0; - int sigalg_seen = 0; s->servername_done = 0; s->tlsext_status_type = -1; @@ -997,6 +1988,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, s->s3->next_proto_neg_seen = 0; # endif + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } # ifndef OPENSSL_NO_HEARTBEATS s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | SSL_TLSEXT_HB_DONT_SEND_REQUESTS); @@ -1007,6 +2002,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, ssl_check_for_safari(s, data, d, n); # endif /* !OPENSSL_NO_EC */ + /* Clear any signature algorithms extension received */ + if (s->cert->peer_sigalgs) { + OPENSSL_free(s->cert->peer_sigalgs); + s->cert->peer_sigalgs = NULL; + } # ifndef OPENSSL_NO_SRP if (s->srp_ctx.login != NULL) { OPENSSL_free(s->srp_ctx.login); @@ -1149,7 +2149,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, unsigned char *sdata = data; int ecpointformatlist_length = *(sdata++); - if (ecpointformatlist_length != size - 1) + if (ecpointformatlist_length != size - 1 || + ecpointformatlist_length < 1) goto err; if (!s->hit) { if (s->session->tlsext_ecpointformatlist) { @@ -1214,8 +2215,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } # endif /* OPENSSL_NO_EC */ # ifdef TLSEXT_TYPE_opaque_prf_input - else if (type == TLSEXT_TYPE_opaque_prf_input && - s->version != DTLS1_VERSION) { + else if (type == TLSEXT_TYPE_opaque_prf_input) { unsigned char *sdata = data; if (size < 2) { @@ -1259,17 +2259,15 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, renegotiate_seen = 1; } else if (type == TLSEXT_TYPE_signature_algorithms) { int dsize; - if (sigalg_seen || size < 2) + if (s->cert->peer_sigalgs || size < 2) goto err; - sigalg_seen = 1; n2s(data, dsize); size -= 2; - if (dsize != size || dsize & 1) + if (dsize != size || dsize & 1 || !dsize) goto err; - if (!tls1_process_sigalgs(s, data, dsize)) + if (!tls1_save_sigalgs(s, data, dsize)) goto err; - } else if (type == TLSEXT_TYPE_status_request && - s->version != DTLS1_VERSION) { + } else if (type == TLSEXT_TYPE_status_request) { if (size < 5) goto err; @@ -1361,7 +2359,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, # endif # ifndef OPENSSL_NO_NEXTPROTONEG else if (type == TLSEXT_TYPE_next_proto_neg && - s->s3->tmp.finish_md_len == 0) { + s->s3->tmp.finish_md_len == 0 && + s->s3->alpn_selected == NULL) { /*- * We shouldn't accept this extension on a * renegotiation. @@ -1383,6 +2382,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } # endif + else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && + s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) { + if (tls1_alpn_handle_client_hello(s, data, size, al) != 0) + return 0; +# ifndef OPENSSL_NO_NEXTPROTONEG + /* ALPN takes precedence over NPN. */ + s->s3->next_proto_neg_seen = 0; +# endif + } + /* session ticket processed earlier */ # ifndef OPENSSL_NO_SRTP else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s) @@ -1408,7 +2417,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, if (!renegotiate_seen && s->renegotiate && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { *al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, + SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); return 0; } @@ -1419,6 +2428,73 @@ err: return 0; } +/* + * Parse any custom extensions found. "data" is the start of the extension data + * and "limit" is the end of the record. TODO: add strict syntax checking. + */ + +static int ssl_scan_clienthello_custom_tlsext(SSL *s, + const unsigned char *data, + const unsigned char *limit, + int *al) +{ + unsigned short type, size, len; + /* If resumed session or no custom extensions nothing to do */ + if (s->hit || s->cert->srv_ext.meths_count == 0) + return 1; + + if (data >= limit - 2) + return 1; + n2s(data, len); + + if (data > limit - len) + return 1; + + while (data <= limit - 4) { + n2s(data, type); + n2s(data, size); + + if (data + size > limit) + return 1; + if (custom_ext_parse(s, 1 /* server */ , type, data, size, al) <= 0) + return 0; + + data += size; + } + + return 1; +} + +int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, + int n) +{ + int al = -1; + unsigned char *ptmp = *p; + /* + * Internally supported extensions are parsed first so SNI can be handled + * before custom extensions. An application processing SNI will typically + * switch the parent context using SSL_set_SSL_CTX and custom extensions + * need to be handled by the new SSL_CTX structure. + */ + if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; + } + + if (ssl_check_clienthello_tlsext_early(s) <= 0) { + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } + + custom_ext_init(&s->cert->srv_ext); + if (ssl_scan_clienthello_custom_tlsext(s, ptmp, d + n, &al) <= 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; + } + + return 1; +} + # ifndef OPENSSL_NO_NEXTPROTONEG /* * ssl_next_proto_validate validates a Next Protocol Negotiation block. No @@ -1440,8 +2516,8 @@ static char ssl_next_proto_validate(unsigned char *d, unsigned len) } # endif -int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, - int n, int *al) +static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, + unsigned char *d, int n, int *al) { unsigned short length; unsigned short type; @@ -1455,6 +2531,10 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, # endif s->tlsext_ticket_expected = 0; + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } # ifndef OPENSSL_NO_HEARTBEATS s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | SSL_TLSEXT_HB_DONT_SEND_REQUESTS); @@ -1491,8 +2571,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, unsigned char *sdata = data; int ecpointformatlist_length = *(sdata++); - if (ecpointformatlist_length != size - 1 || - ecpointformatlist_length < 1) { + if (ecpointformatlist_length != size - 1) { *al = TLS1_AD_DECODE_ERROR; return 0; } @@ -1537,8 +2616,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, s->tlsext_ticket_expected = 1; } # ifdef TLSEXT_TYPE_opaque_prf_input - else if (type == TLSEXT_TYPE_opaque_prf_input && - s->version != DTLS1_VERSION) { + else if (type == TLSEXT_TYPE_opaque_prf_input) { unsigned char *sdata = data; if (size < 2) { @@ -1569,8 +2647,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } } # endif - else if (type == TLSEXT_TYPE_status_request && - s->version != DTLS1_VERSION) { + else if (type == TLSEXT_TYPE_status_request) { /* * MUST be empty and only sent if we've requested a status * request message. @@ -1616,6 +2693,48 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, s->s3->next_proto_neg_seen = 1; } # endif + + else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) { + unsigned len; + + /* We must have requested it. */ + if (s->alpn_client_proto_list == NULL) { + *al = TLS1_AD_UNSUPPORTED_EXTENSION; + return 0; + } + if (size < 4) { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + /*- + * The extension data consists of: + * uint16 list_length + * uint8 proto_length; + * uint8 proto[proto_length]; + */ + len = data[0]; + len <<= 8; + len |= data[1]; + if (len != (unsigned)size - 2) { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + len = data[2]; + if (len != (unsigned)size - 3) { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + if (s->s3->alpn_selected) + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_malloc(len); + if (!s->s3->alpn_selected) { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + memcpy(s->s3->alpn_selected, data + 3, len); + s->s3->alpn_selected_len = len; + } + else if (type == TLSEXT_TYPE_renegotiate) { if (!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) return 0; @@ -1643,6 +2762,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, return 0; } # endif + /* + * If this extension type was not otherwise handled, but matches a + * custom_cli_ext_record, then send it to the c callback + */ + else if (custom_ext_parse(s, 0, type, data, size, al) <= 0) + return 0; data += size; } @@ -1682,7 +2807,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, if (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { *al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); return 0; } @@ -1692,63 +2817,6 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int ssl_prepare_clienthello_tlsext(SSL *s) { -# ifndef OPENSSL_NO_EC - /* - * If we are client and using an elliptic curve cryptography cipher - * suite, send the point formats and elliptic curves we support. - */ - int using_ecc = 0; - int i; - unsigned char *j; - unsigned long alg_k, alg_a; - STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); - - for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) { - SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); - - alg_k = c->algorithm_mkey; - alg_a = c->algorithm_auth; - if ((alg_k & (SSL_kEECDH | SSL_kECDHr | SSL_kECDHe) - || (alg_a & SSL_aECDSA))) { - using_ecc = 1; - break; - } - } - using_ecc = using_ecc && (s->version >= TLS1_VERSION); - if (using_ecc) { - if (s->tlsext_ecpointformatlist != NULL) - OPENSSL_free(s->tlsext_ecpointformatlist); - if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) { - SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT, - ERR_R_MALLOC_FAILURE); - return -1; - } - s->tlsext_ecpointformatlist_length = 3; - s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed; - s->tlsext_ecpointformatlist[1] = - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; - s->tlsext_ecpointformatlist[2] = - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; - - /* we support all named elliptic curves in RFC 4492 */ - if (s->tlsext_ellipticcurvelist != NULL) - OPENSSL_free(s->tlsext_ellipticcurvelist); - s->tlsext_ellipticcurvelist_length = - sizeof(pref_list) / sizeof(pref_list[0]) * 2; - if ((s->tlsext_ellipticcurvelist = - OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) { - s->tlsext_ellipticcurvelist_length = 0; - SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT, - ERR_R_MALLOC_FAILURE); - return -1; - } - for (i = 0, j = s->tlsext_ellipticcurvelist; (unsigned int)i < - sizeof(pref_list) / sizeof(pref_list[0]); i++) { - int id = tls1_ec_nid2curve_id(pref_list[i]); - s2n(id, j); - } - } -# endif /* OPENSSL_NO_EC */ # ifdef TLSEXT_TYPE_opaque_prf_input { @@ -1800,40 +2868,10 @@ int ssl_prepare_clienthello_tlsext(SSL *s) int ssl_prepare_serverhello_tlsext(SSL *s) { -# ifndef OPENSSL_NO_EC - /* - * If we are server and using an ECC cipher suite, send the point formats - * we support if the client sent us an ECPointsFormat extension. Note - * that the server is not supposed to send an EllipticCurves extension. - */ - - unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; - int using_ecc = (alg_k & (SSL_kEECDH | SSL_kECDHr | SSL_kECDHe)) - || (alg_a & SSL_aECDSA); - using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); - - if (using_ecc) { - if (s->tlsext_ecpointformatlist != NULL) - OPENSSL_free(s->tlsext_ecpointformatlist); - if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) { - SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT, - ERR_R_MALLOC_FAILURE); - return -1; - } - s->tlsext_ecpointformatlist_length = 3; - s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed; - s->tlsext_ecpointformatlist[1] = - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; - s->tlsext_ecpointformatlist[2] = - TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; - } -# endif /* OPENSSL_NO_EC */ - return 1; } -int ssl_check_clienthello_tlsext_early(SSL *s) +static int ssl_check_clienthello_tlsext_early(SSL *s) { int ret = SSL_TLSEXT_ERR_NOACK; int al = SSL_AD_UNRECOGNIZED_NAME; @@ -1943,6 +2981,44 @@ int ssl_check_clienthello_tlsext_early(SSL *s) } } +int tls1_set_server_sigalgs(SSL *s) +{ + int al; + size_t i; + /* Clear any shared sigtnature algorithms */ + if (s->cert->shared_sigalgs) { + OPENSSL_free(s->cert->shared_sigalgs); + s->cert->shared_sigalgs = NULL; + s->cert->shared_sigalgslen = 0; + } + /* Clear certificate digests and validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) { + s->cert->pkeys[i].digest = NULL; + s->cert->pkeys[i].valid_flags = 0; + } + + /* If sigalgs received process it. */ + if (s->cert->peer_sigalgs) { + if (!tls1_process_sigalgs(s)) { + SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE); + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + /* Fatal error is no shared signature algorithms */ + if (!s->cert->shared_sigalgs) { + SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, + SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); + al = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + } else + ssl_cert_set_default_md(s->cert); + return 1; + err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; +} + int ssl_check_clienthello_tlsext_late(SSL *s) { int ret = SSL_TLSEXT_ERR_OK; @@ -1950,9 +3026,9 @@ int ssl_check_clienthello_tlsext_late(SSL *s) /* * If status request then ask callback what to do. Note: this must be - * called after servername callbacks in case the certificate has - * changed, and must be called after the cipher has been chosen because - * this may influence which certificate is sent + * called after servername callbacks in case the certificate has changed, + * and must be called after the cipher has been chosen because this may + * influence which certificate is sent */ if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) { int r; @@ -2124,6 +3200,24 @@ int ssl_check_serverhello_tlsext(SSL *s) } } +int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, + int n) +{ + int al = -1; + if (s->version < SSL3_VERSION) + return 1; + if (ssl_scan_serverhello_tlsext(s, p, d, n, &al) <= 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; + } + + if (ssl_check_serverhello_tlsext(s) <= 0) { + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_SERVERHELLO_TLSEXT); + return 0; + } + return 1; +} + /*- * Since the server cache lookup is done early on in the processing of the * ClientHello, and other operations depend on the result, we need to handle @@ -2179,7 +3273,7 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, if (p >= limit) return -1; /* Skip past DTLS cookie */ - if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { + if (SSL_IS_DTLS(s)) { i = *(p++); p += i; if (p >= limit) @@ -2366,32 +3460,18 @@ typedef struct { } tls12_lookup; static tls12_lookup tls12_md[] = { -# ifndef OPENSSL_NO_MD5 {NID_md5, TLSEXT_hash_md5}, -# endif -# ifndef OPENSSL_NO_SHA {NID_sha1, TLSEXT_hash_sha1}, -# endif -# ifndef OPENSSL_NO_SHA256 {NID_sha224, TLSEXT_hash_sha224}, {NID_sha256, TLSEXT_hash_sha256}, -# endif -# ifndef OPENSSL_NO_SHA512 {NID_sha384, TLSEXT_hash_sha384}, {NID_sha512, TLSEXT_hash_sha512} -# endif }; static tls12_lookup tls12_sig[] = { -# ifndef OPENSSL_NO_RSA {EVP_PKEY_RSA, TLSEXT_signature_rsa}, -# endif -# ifndef OPENSSL_NO_DSA {EVP_PKEY_DSA, TLSEXT_signature_dsa}, -# endif -# ifndef OPENSSL_NO_ECDSA {EVP_PKEY_EC, TLSEXT_signature_ecdsa} -# endif }; static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen) @@ -2404,17 +3484,15 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen) return -1; } -# if 0 static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen) { size_t i; for (i = 0; i < tlen; i++) { - if (table[i].id == id) + if ((table[i].id) == id) return table[i].nid; } - return -1; + return NID_undef; } -# endif int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md) @@ -2443,6 +3521,14 @@ int tls12_get_sigid(const EVP_PKEY *pk) const EVP_MD *tls12_get_hash(unsigned char hash_alg) { switch (hash_alg) { +# ifndef OPENSSL_NO_MD5 + case TLSEXT_hash_md5: +# ifdef OPENSSL_FIPS + if (FIPS_mode()) + return NULL; +# endif + return EVP_md5(); +# endif # ifndef OPENSSL_NO_SHA case TLSEXT_hash_sha1: return EVP_sha1(); @@ -2467,83 +3553,274 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg) } } +static int tls12_get_pkey_idx(unsigned char sig_alg) +{ + switch (sig_alg) { +# ifndef OPENSSL_NO_RSA + case TLSEXT_signature_rsa: + return SSL_PKEY_RSA_SIGN; +# endif +# ifndef OPENSSL_NO_DSA + case TLSEXT_signature_dsa: + return SSL_PKEY_DSA_SIGN; +# endif +# ifndef OPENSSL_NO_ECDSA + case TLSEXT_signature_ecdsa: + return SSL_PKEY_ECC; +# endif + } + return -1; +} + +/* Convert TLS 1.2 signature algorithm extension values into NIDs */ +static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, + int *psignhash_nid, const unsigned char *data) +{ + int sign_nid = 0, hash_nid = 0; + if (!phash_nid && !psign_nid && !psignhash_nid) + return; + if (phash_nid || psignhash_nid) { + hash_nid = tls12_find_nid(data[0], tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + if (phash_nid) + *phash_nid = hash_nid; + } + if (psign_nid || psignhash_nid) { + sign_nid = tls12_find_nid(data[1], tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); + if (psign_nid) + *psign_nid = sign_nid; + } + if (psignhash_nid) { + if (sign_nid && hash_nid) + OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid); + else + *psignhash_nid = NID_undef; + } +} + +/* Given preference and allowed sigalgs set shared sigalgs */ +static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, + const unsigned char *pref, size_t preflen, + const unsigned char *allow, + size_t allowlen) +{ + const unsigned char *ptmp, *atmp; + size_t i, j, nmatch = 0; + for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) { + /* Skip disabled hashes or signature algorithms */ + if (tls12_get_hash(ptmp[0]) == NULL) + continue; + if (tls12_get_pkey_idx(ptmp[1]) == -1) + continue; + for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) { + if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) { + nmatch++; + if (shsig) { + shsig->rhash = ptmp[0]; + shsig->rsign = ptmp[1]; + tls1_lookup_sigalg(&shsig->hash_nid, + &shsig->sign_nid, + &shsig->signandhash_nid, ptmp); + shsig++; + } + break; + } + } + } + return nmatch; +} + +/* Set shared signature algorithms for SSL structures */ +static int tls1_set_shared_sigalgs(SSL *s) +{ + const unsigned char *pref, *allow, *conf; + size_t preflen, allowlen, conflen; + size_t nmatch; + TLS_SIGALGS *salgs = NULL; + CERT *c = s->cert; + unsigned int is_suiteb = tls1_suiteb(s); + if (c->shared_sigalgs) { + OPENSSL_free(c->shared_sigalgs); + c->shared_sigalgs = NULL; + c->shared_sigalgslen = 0; + } + /* If client use client signature algorithms if not NULL */ + if (!s->server && c->client_sigalgs && !is_suiteb) { + conf = c->client_sigalgs; + conflen = c->client_sigalgslen; + } else if (c->conf_sigalgs && !is_suiteb) { + conf = c->conf_sigalgs; + conflen = c->conf_sigalgslen; + } else + conflen = tls12_get_psigalgs(s, &conf); + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) { + pref = conf; + preflen = conflen; + allow = c->peer_sigalgs; + allowlen = c->peer_sigalgslen; + } else { + allow = conf; + allowlen = conflen; + pref = c->peer_sigalgs; + preflen = c->peer_sigalgslen; + } + nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen); + if (nmatch) { + salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS)); + if (!salgs) + return 0; + nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen); + } else { + salgs = NULL; + } + c->shared_sigalgs = salgs; + c->shared_sigalgslen = nmatch; + return 1; +} + /* Set preferred digest for each key type */ -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) +int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize) { - int i, idx; - const EVP_MD *md; CERT *c = s->cert; - /* Extension ignored for TLS versions below 1.2 */ - if (TLS1_get_version(s) < TLS1_2_VERSION) + /* Extension ignored for inappropriate versions */ + if (!SSL_USE_SIGALGS(s)) return 1; /* Should never happen */ if (!c) return 0; - c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL; - c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL; - c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL; - c->pkeys[SSL_PKEY_ECC].digest = NULL; + if (c->peer_sigalgs) + OPENSSL_free(c->peer_sigalgs); + c->peer_sigalgs = OPENSSL_malloc(dsize); + if (!c->peer_sigalgs) + return 0; + c->peer_sigalgslen = dsize; + memcpy(c->peer_sigalgs, data, dsize); + return 1; +} - for (i = 0; i < dsize; i += 2) { - unsigned char hash_alg = data[i], sig_alg = data[i + 1]; +int tls1_process_sigalgs(SSL *s) +{ + int idx; + size_t i; + const EVP_MD *md; + CERT *c = s->cert; + TLS_SIGALGS *sigptr; + if (!tls1_set_shared_sigalgs(s)) + return 0; - switch (sig_alg) { -# ifndef OPENSSL_NO_RSA - case TLSEXT_signature_rsa: - idx = SSL_PKEY_RSA_SIGN; - break; -# endif -# ifndef OPENSSL_NO_DSA - case TLSEXT_signature_dsa: - idx = SSL_PKEY_DSA_SIGN; - break; -# endif -# ifndef OPENSSL_NO_ECDSA - case TLSEXT_signature_ecdsa: - idx = SSL_PKEY_ECC; - break; -# endif - default: - continue; +# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) { + /* + * Use first set signature preference to force message digest, + * ignoring any peer preferences. + */ + const unsigned char *sigs = NULL; + if (s->server) + sigs = c->conf_sigalgs; + else + sigs = c->client_sigalgs; + if (sigs) { + idx = tls12_get_pkey_idx(sigs[1]); + md = tls12_get_hash(sigs[0]); + c->pkeys[idx].digest = md; + c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN; + if (idx == SSL_PKEY_RSA_SIGN) { + c->pkeys[SSL_PKEY_RSA_ENC].valid_flags = + CERT_PKEY_EXPLICIT_SIGN; + c->pkeys[SSL_PKEY_RSA_ENC].digest = md; + } } + } +# endif - if (c->pkeys[idx].digest == NULL) { - md = tls12_get_hash(hash_alg); - if (md) { - c->pkeys[idx].digest = md; - if (idx == SSL_PKEY_RSA_SIGN) - c->pkeys[SSL_PKEY_RSA_ENC].digest = md; + for (i = 0, sigptr = c->shared_sigalgs; + i < c->shared_sigalgslen; i++, sigptr++) { + idx = tls12_get_pkey_idx(sigptr->rsign); + if (idx > 0 && c->pkeys[idx].digest == NULL) { + md = tls12_get_hash(sigptr->rhash); + c->pkeys[idx].digest = md; + c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN; + if (idx == SSL_PKEY_RSA_SIGN) { + c->pkeys[SSL_PKEY_RSA_ENC].valid_flags = + CERT_PKEY_EXPLICIT_SIGN; + c->pkeys[SSL_PKEY_RSA_ENC].digest = md; } } } - /* - * Set any remaining keys to default values. NOTE: if alg is not - * supported it stays as NULL. + * In strict mode leave unset digests as NULL to indicate we can't use + * the certificate for signing. */ + if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { + /* + * Set any remaining keys to default values. NOTE: if alg is not + * supported it stays as NULL. + */ # ifndef OPENSSL_NO_DSA - if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest) - c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); + if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest) + c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); # endif # ifndef OPENSSL_NO_RSA - if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) { - c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1(); - c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1(); - } + if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) { + c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1(); + c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1(); + } # endif # ifndef OPENSSL_NO_ECDSA - if (!c->pkeys[SSL_PKEY_ECC].digest) - c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); + if (!c->pkeys[SSL_PKEY_ECC].digest) + c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); # endif + } return 1; } -#endif +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignhash, + unsigned char *rsig, unsigned char *rhash) +{ + const unsigned char *psig = s->cert->peer_sigalgs; + if (psig == NULL) + return 0; + if (idx >= 0) { + idx <<= 1; + if (idx >= (int)s->cert->peer_sigalgslen) + return 0; + psig += idx; + if (rhash) + *rhash = psig[0]; + if (rsig) + *rsig = psig[1]; + tls1_lookup_sigalg(phash, psign, psignhash, psig); + } + return s->cert->peer_sigalgslen / 2; +} -#ifndef OPENSSL_NO_HEARTBEATS +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignhash, + unsigned char *rsig, unsigned char *rhash) +{ + TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs; + if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen) + return 0; + shsigalgs += idx; + if (phash) + *phash = shsigalgs->hash_nid; + if (psign) + *psign = shsigalgs->sign_nid; + if (psignhash) + *psignhash = shsigalgs->signandhash_nid; + if (rsig) + *rsig = shsigalgs->rsign; + if (rhash) + *rhash = shsigalgs->rhash; + return s->cert->shared_sigalgslen; +} + +# ifndef OPENSSL_NO_HEARTBEATS int tls1_process_heartbeat(SSL *s) { unsigned char *p = &s->s3->rrec.data[0], *pl; @@ -2694,4 +3971,426 @@ err: return ret; } +# endif + +# define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2) + +typedef struct { + size_t sigalgcnt; + int sigalgs[MAX_SIGALGLEN]; +} sig_cb_st; + +static int sig_cb(const char *elem, int len, void *arg) +{ + sig_cb_st *sarg = arg; + size_t i; + char etmp[20], *p; + int sig_alg, hash_alg; + if (elem == NULL) + return 0; + if (sarg->sigalgcnt == MAX_SIGALGLEN) + return 0; + if (len > (int)(sizeof(etmp) - 1)) + return 0; + memcpy(etmp, elem, len); + etmp[len] = 0; + p = strchr(etmp, '+'); + if (!p) + return 0; + *p = 0; + p++; + if (!*p) + return 0; + + if (!strcmp(etmp, "RSA")) + sig_alg = EVP_PKEY_RSA; + else if (!strcmp(etmp, "DSA")) + sig_alg = EVP_PKEY_DSA; + else if (!strcmp(etmp, "ECDSA")) + sig_alg = EVP_PKEY_EC; + else + return 0; + + hash_alg = OBJ_sn2nid(p); + if (hash_alg == NID_undef) + hash_alg = OBJ_ln2nid(p); + if (hash_alg == NID_undef) + return 0; + + for (i = 0; i < sarg->sigalgcnt; i += 2) { + if (sarg->sigalgs[i] == sig_alg && sarg->sigalgs[i + 1] == hash_alg) + return 0; + } + sarg->sigalgs[sarg->sigalgcnt++] = hash_alg; + sarg->sigalgs[sarg->sigalgcnt++] = sig_alg; + return 1; +} + +/* + * Set suppored signature algorithms based on a colon separated list of the + * form sig+hash e.g. RSA+SHA512:DSA+SHA512 + */ +int tls1_set_sigalgs_list(CERT *c, const char *str, int client) +{ + sig_cb_st sig; + sig.sigalgcnt = 0; + if (!CONF_parse_list(str, ':', 1, sig_cb, &sig)) + return 0; + if (c == NULL) + return 1; + return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client); +} + +int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, + int client) +{ + unsigned char *sigalgs, *sptr; + int rhash, rsign; + size_t i; + if (salglen & 1) + return 0; + sigalgs = OPENSSL_malloc(salglen); + if (sigalgs == NULL) + return 0; + for (i = 0, sptr = sigalgs; i < salglen; i += 2) { + rhash = tls12_find_id(*psig_nids++, tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + rsign = tls12_find_id(*psig_nids++, tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); + + if (rhash == -1 || rsign == -1) + goto err; + *sptr++ = rhash; + *sptr++ = rsign; + } + + if (client) { + if (c->client_sigalgs) + OPENSSL_free(c->client_sigalgs); + c->client_sigalgs = sigalgs; + c->client_sigalgslen = salglen; + } else { + if (c->conf_sigalgs) + OPENSSL_free(c->conf_sigalgs); + c->conf_sigalgs = sigalgs; + c->conf_sigalgslen = salglen; + } + + return 1; + + err: + OPENSSL_free(sigalgs); + return 0; +} + +static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid) +{ + int sig_nid; + size_t i; + if (default_nid == -1) + return 1; + sig_nid = X509_get_signature_nid(x); + if (default_nid) + return sig_nid == default_nid ? 1 : 0; + for (i = 0; i < c->shared_sigalgslen; i++) + if (sig_nid == c->shared_sigalgs[i].signandhash_nid) + return 1; + return 0; +} + +/* Check to see if a certificate issuer name matches list of CA names */ +static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x) +{ + X509_NAME *nm; + int i; + nm = X509_get_issuer_name(x); + for (i = 0; i < sk_X509_NAME_num(names); i++) { + if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i))) + return 1; + } + return 0; +} + +/* + * Check certificate chain is consistent with TLS extensions and is usable by + * server. This servers two purposes: it allows users to check chains before + * passing them to the server and it allows the server to check chains before + * attempting to use them. + */ + +/* Flags which need to be set for a certificate when stict mode not set */ + +# define CERT_PKEY_VALID_FLAGS \ + (CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM) +/* Strict mode flags */ +# define CERT_PKEY_STRICT_FLAGS \ + (CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \ + | CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE) + +int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, + int idx) +{ + int i; + int rv = 0; + int check_flags = 0, strict_mode; + CERT_PKEY *cpk = NULL; + CERT *c = s->cert; + unsigned int suiteb_flags = tls1_suiteb(s); + /* idx == -1 means checking server chains */ + if (idx != -1) { + /* idx == -2 means checking client certificate chains */ + if (idx == -2) { + cpk = c->key; + idx = cpk - c->pkeys; + } else + cpk = c->pkeys + idx; + x = cpk->x509; + pk = cpk->privatekey; + chain = cpk->chain; + strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT; + /* If no cert or key, forget it */ + if (!x || !pk) + goto end; +# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* Allow any certificate to pass test */ + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) { + rv = CERT_PKEY_STRICT_FLAGS | CERT_PKEY_EXPLICIT_SIGN | + CERT_PKEY_VALID | CERT_PKEY_SIGN; + cpk->valid_flags = rv; + return rv; + } +# endif + } else { + if (!x || !pk) + return 0; + idx = ssl_cert_type(x, pk); + if (idx == -1) + return 0; + cpk = c->pkeys + idx; + if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT) + check_flags = CERT_PKEY_STRICT_FLAGS; + else + check_flags = CERT_PKEY_VALID_FLAGS; + strict_mode = 1; + } + + if (suiteb_flags) { + int ok; + if (check_flags) + check_flags |= CERT_PKEY_SUITEB; + ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags); + if (ok == X509_V_OK) + rv |= CERT_PKEY_SUITEB; + else if (!check_flags) + goto end; + } + + /* + * Check all signature algorithms are consistent with signature + * algorithms extension if TLS 1.2 or later and strict mode. + */ + if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) { + int default_nid; + unsigned char rsign = 0; + if (c->peer_sigalgs) + default_nid = 0; + /* If no sigalgs extension use defaults from RFC5246 */ + else { + switch (idx) { + case SSL_PKEY_RSA_ENC: + case SSL_PKEY_RSA_SIGN: + case SSL_PKEY_DH_RSA: + rsign = TLSEXT_signature_rsa; + default_nid = NID_sha1WithRSAEncryption; + break; + + case SSL_PKEY_DSA_SIGN: + case SSL_PKEY_DH_DSA: + rsign = TLSEXT_signature_dsa; + default_nid = NID_dsaWithSHA1; + break; + + case SSL_PKEY_ECC: + rsign = TLSEXT_signature_ecdsa; + default_nid = NID_ecdsa_with_SHA1; + break; + + default: + default_nid = -1; + break; + } + } + /* + * If peer sent no signature algorithms extension and we have set + * preferred signature algorithms check we support sha1. + */ + if (default_nid > 0 && c->conf_sigalgs) { + size_t j; + const unsigned char *p = c->conf_sigalgs; + for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) { + if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign) + break; + } + if (j == c->conf_sigalgslen) { + if (check_flags) + goto skip_sigs; + else + goto end; + } + } + /* Check signature algorithm of each cert in chain */ + if (!tls1_check_sig_alg(c, x, default_nid)) { + if (!check_flags) + goto end; + } else + rv |= CERT_PKEY_EE_SIGNATURE; + rv |= CERT_PKEY_CA_SIGNATURE; + for (i = 0; i < sk_X509_num(chain); i++) { + if (!tls1_check_sig_alg(c, sk_X509_value(chain, i), default_nid)) { + if (check_flags) { + rv &= ~CERT_PKEY_CA_SIGNATURE; + break; + } else + goto end; + } + } + } + /* Else not TLS 1.2, so mark EE and CA signing algorithms OK */ + else if (check_flags) + rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE; + skip_sigs: + /* Check cert parameters are consistent */ + if (tls1_check_cert_param(s, x, check_flags ? 1 : 2)) + rv |= CERT_PKEY_EE_PARAM; + else if (!check_flags) + goto end; + if (!s->server) + rv |= CERT_PKEY_CA_PARAM; + /* In strict mode check rest of chain too */ + else if (strict_mode) { + rv |= CERT_PKEY_CA_PARAM; + for (i = 0; i < sk_X509_num(chain); i++) { + X509 *ca = sk_X509_value(chain, i); + if (!tls1_check_cert_param(s, ca, 0)) { + if (check_flags) { + rv &= ~CERT_PKEY_CA_PARAM; + break; + } else + goto end; + } + } + } + if (!s->server && strict_mode) { + STACK_OF(X509_NAME) *ca_dn; + int check_type = 0; + switch (pk->type) { + case EVP_PKEY_RSA: + check_type = TLS_CT_RSA_SIGN; + break; + case EVP_PKEY_DSA: + check_type = TLS_CT_DSS_SIGN; + break; + case EVP_PKEY_EC: + check_type = TLS_CT_ECDSA_SIGN; + break; + case EVP_PKEY_DH: + case EVP_PKEY_DHX: + { + int cert_type = X509_certificate_type(x, pk); + if (cert_type & EVP_PKS_RSA) + check_type = TLS_CT_RSA_FIXED_DH; + if (cert_type & EVP_PKS_DSA) + check_type = TLS_CT_DSS_FIXED_DH; + } + } + if (check_type) { + const unsigned char *ctypes; + int ctypelen; + if (c->ctypes) { + ctypes = c->ctypes; + ctypelen = (int)c->ctype_num; + } else { + ctypes = (unsigned char *)s->s3->tmp.ctype; + ctypelen = s->s3->tmp.ctype_num; + } + for (i = 0; i < ctypelen; i++) { + if (ctypes[i] == check_type) { + rv |= CERT_PKEY_CERT_TYPE; + break; + } + } + if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags) + goto end; + } else + rv |= CERT_PKEY_CERT_TYPE; + + ca_dn = s->s3->tmp.ca_names; + + if (!sk_X509_NAME_num(ca_dn)) + rv |= CERT_PKEY_ISSUER_NAME; + + if (!(rv & CERT_PKEY_ISSUER_NAME)) { + if (ssl_check_ca_name(ca_dn, x)) + rv |= CERT_PKEY_ISSUER_NAME; + } + if (!(rv & CERT_PKEY_ISSUER_NAME)) { + for (i = 0; i < sk_X509_num(chain); i++) { + X509 *xtmp = sk_X509_value(chain, i); + if (ssl_check_ca_name(ca_dn, xtmp)) { + rv |= CERT_PKEY_ISSUER_NAME; + break; + } + } + } + if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME)) + goto end; + } else + rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE; + + if (!check_flags || (rv & check_flags) == check_flags) + rv |= CERT_PKEY_VALID; + + end: + + if (TLS1_get_version(s) >= TLS1_2_VERSION) { + if (cpk->valid_flags & CERT_PKEY_EXPLICIT_SIGN) + rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN; + else if (cpk->digest) + rv |= CERT_PKEY_SIGN; + } else + rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN; + + /* + * When checking a CERT_PKEY structure all flags are irrelevant if the + * chain is invalid. + */ + if (!check_flags) { + if (rv & CERT_PKEY_VALID) + cpk->valid_flags = rv; + else { + /* Preserve explicit sign flag, clear rest */ + cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN; + return 0; + } + } + return rv; +} + +/* Set validity of certificates in an SSL structure */ +void tls1_set_cert_validity(SSL *s) +{ + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_RSA); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_DSA); + tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC); +} + +/* User level utiity function to check a chain is suitable */ +int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) +{ + return tls1_check_chain(s, x, pk, chain, -1); +} + #endif diff --git a/ssl/t1_meth.c b/ssl/t1_meth.c index 4a1b0529b882..335d57b530f7 100644 --- a/ssl/t1_meth.c +++ b/ssl/t1_meth.c @@ -72,10 +72,13 @@ static const SSL_METHOD *tls1_get_method(int ver) } IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_method, - ssl3_accept, ssl3_connect, tls1_get_method) + ssl3_accept, + ssl3_connect, tls1_get_method, TLSv1_2_enc_data) IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method, - ssl3_accept, ssl3_connect, tls1_get_method) + ssl3_accept, + ssl3_connect, tls1_get_method, TLSv1_1_enc_data) IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method, - ssl3_accept, ssl3_connect, tls1_get_method) + ssl3_accept, + ssl3_connect, tls1_get_method, TLSv1_enc_data) diff --git a/ssl/t1_srvr.c b/ssl/t1_srvr.c index 076ec86e89a4..8c6b3dff2f55 100644 --- a/ssl/t1_srvr.c +++ b/ssl/t1_srvr.c @@ -78,12 +78,15 @@ static const SSL_METHOD *tls1_get_server_method(int ver) IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_server_method, ssl3_accept, - ssl_undefined_function, tls1_get_server_method) + ssl_undefined_function, + tls1_get_server_method, TLSv1_2_enc_data) IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method, ssl3_accept, - ssl_undefined_function, tls1_get_server_method) + ssl_undefined_function, + tls1_get_server_method, TLSv1_1_enc_data) IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_server_method, ssl3_accept, - ssl_undefined_function, tls1_get_server_method) + ssl_undefined_function, + tls1_get_server_method, TLSv1_enc_data) diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c new file mode 100644 index 000000000000..c5e21df77a6b --- /dev/null +++ b/ssl/t1_trce.c @@ -0,0 +1,1266 @@ +/* ssl/t1_trce.c */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#include "ssl_locl.h" + +#ifndef OPENSSL_NO_SSL_TRACE + +/* Packet trace support for OpenSSL */ + +typedef struct { + int num; + const char *name; +} ssl_trace_tbl; + +# define ssl_trace_str(val, tbl) \ + do_ssl_trace_str(val, tbl, sizeof(tbl)/sizeof(ssl_trace_tbl)) + +# define ssl_trace_list(bio, indent, msg, msglen, value, table) \ + do_ssl_trace_list(bio, indent, msg, msglen, value, \ + table, sizeof(table)/sizeof(ssl_trace_tbl)) + +static const char *do_ssl_trace_str(int val, ssl_trace_tbl *tbl, size_t ntbl) +{ + size_t i; + for (i = 0; i < ntbl; i++, tbl++) { + if (tbl->num == val) + return tbl->name; + } + return "UNKNOWN"; +} + +static int do_ssl_trace_list(BIO *bio, int indent, + const unsigned char *msg, size_t msglen, + size_t vlen, ssl_trace_tbl *tbl, size_t ntbl) +{ + int val; + if (msglen % vlen) + return 0; + while (msglen) { + val = msg[0]; + if (vlen == 2) + val = (val << 8) | msg[1]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s (%d)\n", do_ssl_trace_str(val, tbl, ntbl), val); + msg += vlen; + msglen -= vlen; + } + return 1; +} + +/* Version number */ + +static ssl_trace_tbl ssl_version_tbl[] = { + {SSL2_VERSION, "SSL 2.0"}, + {SSL3_VERSION, "SSL 3.0"}, + {TLS1_VERSION, "TLS 1.0"}, + {TLS1_1_VERSION, "TLS 1.1"}, + {TLS1_2_VERSION, "TLS 1.2"}, + {DTLS1_VERSION, "DTLS 1.0"}, + {DTLS1_2_VERSION, "DTLS 1.2"}, + {DTLS1_BAD_VER, "DTLS 1.0 (bad)"} +}; + +static ssl_trace_tbl ssl_content_tbl[] = { + {SSL3_RT_CHANGE_CIPHER_SPEC, "ChangeCipherSpec"}, + {SSL3_RT_ALERT, "Alert"}, + {SSL3_RT_HANDSHAKE, "Handshake"}, + {SSL3_RT_APPLICATION_DATA, "ApplicationData"}, + {TLS1_RT_HEARTBEAT, "HeartBeat"} +}; + +/* Handshake types */ +static ssl_trace_tbl ssl_handshake_tbl[] = { + {SSL3_MT_HELLO_REQUEST, "HelloRequest"}, + {SSL3_MT_CLIENT_HELLO, "ClientHello"}, + {SSL3_MT_SERVER_HELLO, "ServerHello"}, + {DTLS1_MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest"}, + {SSL3_MT_NEWSESSION_TICKET, "NewSessionTicket"}, + {SSL3_MT_CERTIFICATE, "Certificate"}, + {SSL3_MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange"}, + {SSL3_MT_CERTIFICATE_REQUEST, "CertificateRequest"}, + {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"}, + {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"}, + {SSL3_MT_SERVER_DONE, "ServerHelloDone"}, + {SSL3_MT_CERTIFICATE_VERIFY, "CertificateVerify"}, + {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"}, + {SSL3_MT_FINISHED, "Finished"}, + {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"} +}; + +/* Cipher suites */ +static ssl_trace_tbl ssl_ciphers_tbl[] = { + {0x0000, "SSL_NULL_WITH_NULL_NULL"}, + {0x0001, "SSL_RSA_WITH_NULL_MD5"}, + {0x0002, "SSL_RSA_WITH_NULL_SHA"}, + {0x0003, "SSL_RSA_EXPORT_WITH_RC4_40_MD5"}, + {0x0004, "SSL_RSA_WITH_RC4_128_MD5"}, + {0x0005, "SSL_RSA_WITH_RC4_128_SHA"}, + {0x0006, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"}, + {0x0007, "SSL_RSA_WITH_IDEA_CBC_SHA"}, + {0x0008, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0009, "SSL_RSA_WITH_DES_CBC_SHA"}, + {0x000A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x000B, "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {0x000C, "SSL_DH_DSS_WITH_DES_CBC_SHA"}, + {0x000D, "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0x000E, "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x000F, "SSL_DH_RSA_WITH_DES_CBC_SHA"}, + {0x0010, "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x0011, "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0012, "SSL_DHE_DSS_WITH_DES_CBC_SHA"}, + {0x0013, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0x0014, "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"}, + {0x0015, "SSL_DHE_RSA_WITH_DES_CBC_SHA"}, + {0x0016, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0x0017, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"}, + {0x0018, "SSL_DH_anon_WITH_RC4_128_MD5"}, + {0x0019, "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}, + {0x001A, "SSL_DH_anon_WITH_DES_CBC_SHA"}, + {0x001B, "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"}, + {0x001D, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"}, + {0x001E, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"}, + {0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"}, + {0x0020, "TLS_KRB5_WITH_RC4_128_SHA"}, + {0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA"}, + {0x0022, "TLS_KRB5_WITH_DES_CBC_MD5"}, + {0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"}, + {0x0024, "TLS_KRB5_WITH_RC4_128_MD5"}, + {0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5"}, + {0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"}, + {0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"}, + {0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"}, + {0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"}, + {0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"}, + {0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"}, + {0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA"}, + {0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"}, + {0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"}, + {0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"}, + {0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}, + {0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA"}, + {0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA"}, + {0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"}, + {0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"}, + {0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"}, + {0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"}, + {0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA"}, + {0x003B, "TLS_RSA_WITH_NULL_SHA256"}, + {0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256"}, + {0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256"}, + {0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"}, + {0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"}, + {0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"}, + {0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"}, + {0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"}, + {0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"}, + {0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"}, + {0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"}, + {0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"}, + {0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"}, + {0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"}, + {0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"}, + {0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"}, + {0x008A, "TLS_PSK_WITH_RC4_128_SHA"}, + {0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA"}, + {0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA"}, + {0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA"}, + {0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"}, + {0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"}, + {0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA"}, + {0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"}, + {0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"}, + {0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"}, + {0x0096, "TLS_RSA_WITH_SEED_CBC_SHA"}, + {0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA"}, + {0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA"}, + {0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"}, + {0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"}, + {0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA"}, + {0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256"}, + {0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384"}, + {0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"}, + {0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"}, + {0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"}, + {0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"}, + {0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"}, + {0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"}, + {0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"}, + {0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"}, + {0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"}, + {0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"}, + {0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"}, + {0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"}, + {0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B0, "TLS_PSK_WITH_NULL_SHA256"}, + {0x00B1, "TLS_PSK_WITH_NULL_SHA384"}, + {0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256"}, + {0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384"}, + {0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"}, + {0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"}, + {0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256"}, + {0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384"}, + {0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"}, + {0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"}, + {0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"}, + {0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA"}, + {0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"}, + {0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"}, + {0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"}, + {0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"}, + {0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"}, + {0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"}, + {0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"}, + {0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA"}, + {0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA"}, + {0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"}, + {0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"}, + {0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA"}, + {0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"}, + {0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}, + {0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"}, + {0xC015, "TLS_ECDH_anon_WITH_NULL_SHA"}, + {0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA"}, + {0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"}, + {0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"}, + {0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"}, + {0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"}, + {0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"}, + {0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"}, + {0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"}, + {0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"}, + {0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"}, + {0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"}, + {0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"}, + {0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"}, + {0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}, + {0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"}, + {0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"}, + {0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"}, + {0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}, + {0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"}, + {0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"}, + {0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"}, + {0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, + {0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"}, + {0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"}, + {0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"}, + {0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}, + {0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"}, + {0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"}, + {0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"}, + {0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"}, + {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"}, +}; + +/* Compression methods */ +static ssl_trace_tbl ssl_comp_tbl[] = { + {0x0000, "No Compression"}, + {0x0001, "Zlib Compression"} +}; + +/* Extensions */ +static ssl_trace_tbl ssl_exts_tbl[] = { + {TLSEXT_TYPE_server_name, "server_name"}, + {TLSEXT_TYPE_max_fragment_length, "max_fragment_length"}, + {TLSEXT_TYPE_client_certificate_url, "client_certificate_url"}, + {TLSEXT_TYPE_trusted_ca_keys, "trusted_ca_keys"}, + {TLSEXT_TYPE_truncated_hmac, "truncated_hmac"}, + {TLSEXT_TYPE_status_request, "status_request"}, + {TLSEXT_TYPE_user_mapping, "user_mapping"}, + {TLSEXT_TYPE_client_authz, "client_authz"}, + {TLSEXT_TYPE_server_authz, "server_authz"}, + {TLSEXT_TYPE_cert_type, "cert_type"}, + {TLSEXT_TYPE_elliptic_curves, "elliptic_curves"}, + {TLSEXT_TYPE_ec_point_formats, "ec_point_formats"}, + {TLSEXT_TYPE_srp, "srp"}, + {TLSEXT_TYPE_signature_algorithms, "signature_algorithms"}, + {TLSEXT_TYPE_use_srtp, "use_srtp"}, + {TLSEXT_TYPE_heartbeat, "heartbeat"}, + {TLSEXT_TYPE_session_ticket, "session_ticket"}, +# ifdef TLSEXT_TYPE_opaque_prf_input + {TLSEXT_TYPE_opaque_prf_input, "opaque_prf_input"}, +# endif + {TLSEXT_TYPE_renegotiate, "renegotiate"}, + {TLSEXT_TYPE_next_proto_neg, "next_proto_neg"}, + {TLSEXT_TYPE_padding, "padding"} +}; + +static ssl_trace_tbl ssl_curve_tbl[] = { + {1, "sect163k1 (K-163)"}, + {2, "sect163r1"}, + {3, "sect163r2 (B-163)"}, + {4, "sect193r1"}, + {5, "sect193r2"}, + {6, "sect233k1 (K-233)"}, + {7, "sect233r1 (B-233)"}, + {8, "sect239k1"}, + {9, "sect283k1 (K-283)"}, + {10, "sect283r1 (B-283)"}, + {11, "sect409k1 (K-409)"}, + {12, "sect409r1 (B-409)"}, + {13, "sect571k1 (K-571)"}, + {14, "sect571r1 (B-571)"}, + {15, "secp160k1"}, + {16, "secp160r1"}, + {17, "secp160r2"}, + {18, "secp192k1"}, + {19, "secp192r1 (P-192)"}, + {20, "secp224k1"}, + {21, "secp224r1 (P-224)"}, + {22, "secp256k1"}, + {23, "secp256r1 (P-256)"}, + {24, "secp384r1 (P-384)"}, + {25, "secp521r1 (P-521)"}, + {26, "brainpoolP256r1"}, + {27, "brainpoolP384r1"}, + {28, "brainpoolP512r1"}, + {0xFF01, "arbitrary_explicit_prime_curves"}, + {0xFF02, "arbitrary_explicit_char2_curves"} +}; + +static ssl_trace_tbl ssl_point_tbl[] = { + {0, "uncompressed"}, + {1, "ansiX962_compressed_prime"}, + {2, "ansiX962_compressed_char2"} +}; + +static ssl_trace_tbl ssl_md_tbl[] = { + {0, "none"}, + {1, "md5"}, + {2, "sha1"}, + {3, "sha224"}, + {4, "sha256"}, + {5, "sha384"}, + {6, "sha512"} +}; + +static ssl_trace_tbl ssl_sig_tbl[] = { + {0, "anonymous"}, + {1, "rsa"}, + {2, "dsa"}, + {3, "ecdsa"} +}; + +static ssl_trace_tbl ssl_hb_tbl[] = { + {1, "peer_allowed_to_send"}, + {2, "peer_not_allowed_to_send"} +}; + +static ssl_trace_tbl ssl_hb_type_tbl[] = { + {1, "heartbeat_request"}, + {2, "heartbeat_response"} +}; + +static ssl_trace_tbl ssl_ctype_tbl[] = { + {1, "rsa_sign"}, + {2, "dss_sign"}, + {3, "rsa_fixed_dh"}, + {4, "dss_fixed_dh"}, + {5, "rsa_ephemeral_dh"}, + {6, "dss_ephemeral_dh"}, + {20, "fortezza_dms"}, + {64, "ecdsa_sign"}, + {65, "rsa_fixed_ecdh"}, + {66, "ecdsa_fixed_ecdh"} +}; + +static ssl_trace_tbl ssl_crypto_tbl[] = { + {TLS1_RT_CRYPTO_PREMASTER, "Premaster Secret"}, + {TLS1_RT_CRYPTO_CLIENT_RANDOM, "Client Random"}, + {TLS1_RT_CRYPTO_SERVER_RANDOM, "Server Random"}, + {TLS1_RT_CRYPTO_MASTER, "Master Secret"}, + {TLS1_RT_CRYPTO_MAC | TLS1_RT_CRYPTO_WRITE, "Write Mac Secret"}, + {TLS1_RT_CRYPTO_MAC | TLS1_RT_CRYPTO_READ, "Read Mac Secret"}, + {TLS1_RT_CRYPTO_KEY | TLS1_RT_CRYPTO_WRITE, "Write Key"}, + {TLS1_RT_CRYPTO_KEY | TLS1_RT_CRYPTO_READ, "Read Key"}, + {TLS1_RT_CRYPTO_IV | TLS1_RT_CRYPTO_WRITE, "Write IV"}, + {TLS1_RT_CRYPTO_IV | TLS1_RT_CRYPTO_READ, "Read IV"}, + {TLS1_RT_CRYPTO_FIXED_IV | TLS1_RT_CRYPTO_WRITE, "Write IV (fixed part)"}, + {TLS1_RT_CRYPTO_FIXED_IV | TLS1_RT_CRYPTO_READ, "Read IV (fixed part)"} +}; + +static void ssl_print_hex(BIO *bio, int indent, const char *name, + const unsigned char *msg, size_t msglen) +{ + size_t i; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s (len=%d): ", name, (int)msglen); + for (i = 0; i < msglen; i++) + BIO_printf(bio, "%02X", msg[i]); + BIO_puts(bio, "\n"); +} + +static int ssl_print_hexbuf(BIO *bio, int indent, + const char *name, size_t nlen, + const unsigned char **pmsg, size_t *pmsglen) +{ + size_t blen; + const unsigned char *p = *pmsg; + if (*pmsglen < nlen) + return 0; + blen = p[0]; + if (nlen > 1) + blen = (blen << 8) | p[1]; + if (*pmsglen < nlen + blen) + return 0; + p += nlen; + ssl_print_hex(bio, indent, name, p, blen); + *pmsg += blen + nlen; + *pmsglen -= blen + nlen; + return 1; +} + +static int ssl_print_version(BIO *bio, int indent, const char *name, + const unsigned char **pmsg, size_t *pmsglen) +{ + int vers; + if (*pmsglen < 2) + return 0; + vers = ((*pmsg)[0] << 8) | (*pmsg)[1]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s=0x%x (%s)\n", + name, vers, ssl_trace_str(vers, ssl_version_tbl)); + *pmsg += 2; + *pmsglen -= 2; + return 1; +} + +static int ssl_print_random(BIO *bio, int indent, + const unsigned char **pmsg, size_t *pmsglen) +{ + unsigned int tm; + const unsigned char *p = *pmsg; + if (*pmsglen < 32) + return 0; + tm = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + BIO_indent(bio, indent, 80); + BIO_puts(bio, "Random:\n"); + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "gmt_unix_time=0x%08X\n", tm); + ssl_print_hex(bio, indent + 2, "random_bytes", p, 28); + *pmsg += 32; + *pmsglen -= 32; + return 1; +} + +static int ssl_print_signature(BIO *bio, int indent, SSL *s, + const unsigned char **pmsg, size_t *pmsglen) +{ + if (*pmsglen < 2) + return 0; + if (SSL_USE_SIGALGS(s)) { + const unsigned char *p = *pmsg; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "Signature Algorithm %s+%s (%d+%d)\n", + ssl_trace_str(p[0], ssl_md_tbl), + ssl_trace_str(p[1], ssl_sig_tbl), p[0], p[1]); + *pmsg += 2; + *pmsglen -= 2; + } + return ssl_print_hexbuf(bio, indent, "Signature", 2, pmsg, pmsglen); +} + +static int ssl_print_extension(BIO *bio, int indent, int server, int extype, + const unsigned char *ext, size_t extlen) +{ + size_t xlen; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "extension_type=%s(%d), length=%d\n", + ssl_trace_str(extype, ssl_exts_tbl), extype, (int)extlen); + switch (extype) { + case TLSEXT_TYPE_ec_point_formats: + if (extlen < 1) + return 0; + xlen = ext[0]; + if (extlen != xlen + 1) + return 0; + return ssl_trace_list(bio, indent + 2, + ext + 1, xlen, 1, ssl_point_tbl); + + case TLSEXT_TYPE_elliptic_curves: + if (extlen < 2) + return 0; + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + return ssl_trace_list(bio, indent + 2, + ext + 2, xlen, 2, ssl_curve_tbl); + + case TLSEXT_TYPE_signature_algorithms: + + if (extlen < 2) + return 0; + xlen = (ext[0] << 8) | ext[1]; + if (extlen != xlen + 2) + return 0; + if (xlen & 1) + return 0; + ext += 2; + while (xlen > 0) { + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "%s+%s (%d+%d)\n", + ssl_trace_str(ext[0], ssl_md_tbl), + ssl_trace_str(ext[1], ssl_sig_tbl), ext[0], ext[1]); + xlen -= 2; + ext += 2; + } + break; + + case TLSEXT_TYPE_renegotiate: + if (extlen < 1) + return 0; + xlen = ext[0]; + if (xlen + 1 != extlen) + return 0; + ext++; + if (xlen) { + if (server) { + if (xlen & 1) + return 0; + xlen >>= 1; + } + ssl_print_hex(bio, indent + 4, "client_verify_data", ext, xlen); + if (server) { + ext += xlen; + ssl_print_hex(bio, indent + 4, + "server_verify_data", ext, xlen); + } + } else { + BIO_indent(bio, indent + 4, 80); + BIO_puts(bio, "<EMPTY>\n"); + } + break; + + case TLSEXT_TYPE_heartbeat: + if (extlen != 1) + return 0; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "HeartbeatMode: %s\n", + ssl_trace_str(ext[0], ssl_hb_tbl)); + break; + + case TLSEXT_TYPE_session_ticket: + if (extlen != 0) + ssl_print_hex(bio, indent + 4, "ticket", ext, extlen); + break; + + default: + BIO_dump_indent(bio, (char *)ext, extlen, indent + 2); + } + return 1; +} + +static int ssl_print_extensions(BIO *bio, int indent, int server, + const unsigned char *msg, size_t msglen) +{ + size_t extslen; + BIO_indent(bio, indent, 80); + if (msglen == 0) { + BIO_puts(bio, "No Extensions\n"); + return 1; + } + extslen = (msg[0] << 8) | msg[1]; + if (extslen != msglen - 2) + return 0; + msg += 2; + msglen = extslen; + BIO_printf(bio, "extensions, length = %d\n", (int)msglen); + while (msglen > 0) { + int extype; + size_t extlen; + if (msglen < 4) + return 0; + extype = (msg[0] << 8) | msg[1]; + extlen = (msg[2] << 8) | msg[3]; + if (msglen < extlen + 4) + return 0; + msg += 4; + if (!ssl_print_extension(bio, indent + 2, server, + extype, msg, extlen)) + return 0; + msg += extlen; + msglen -= extlen + 4; + } + return 1; +} + +static int ssl_print_client_hello(BIO *bio, SSL *ssl, int indent, + const unsigned char *msg, size_t msglen) +{ + size_t len; + unsigned int cs; + if (!ssl_print_version(bio, indent, "client_version", &msg, &msglen)) + return 0; + if (!ssl_print_random(bio, indent, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen)) + return 0; + if (SSL_IS_DTLS(ssl)) { + if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen)) + return 0; + } + if (msglen < 2) + return 0; + len = (msg[0] << 8) | msg[1]; + msg += 2; + msglen -= 2; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "cipher_suites (len=%d)\n", (int)len); + if (msglen < len || len & 1) + return 0; + while (len > 0) { + cs = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "{0x%02X, 0x%02X} %s\n", + msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl)); + msg += 2; + msglen -= 2; + len -= 2; + } + if (msglen < 1) + return 0; + len = msg[0]; + msg++; + msglen--; + if (msglen < len) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "compression_methods (len=%d)\n", (int)len); + while (len > 0) { + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "%s (0x%02X)\n", + ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]); + msg++; + msglen--; + len--; + } + if (!ssl_print_extensions(bio, indent, 0, msg, msglen)) + return 0; + return 1; +} + +static int dtls_print_hello_vfyrequest(BIO *bio, int indent, + const unsigned char *msg, + size_t msglen) +{ + if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent, "cookie", 1, &msg, &msglen)) + return 0; + return 1; +} + +static int ssl_print_server_hello(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + unsigned int cs; + if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen)) + return 0; + if (!ssl_print_random(bio, indent, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent, "session_id", 1, &msg, &msglen)) + return 0; + if (msglen < 2) + return 0; + cs = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "cipher_suite {0x%02X, 0x%02X} %s\n", + msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl)); + msg += 2; + msglen -= 2; + if (msglen < 1) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "compression_method: %s (0x%02X)\n", + ssl_trace_str(msg[0], ssl_comp_tbl), msg[0]); + msg++; + msglen--; + if (!ssl_print_extensions(bio, indent, 1, msg, msglen)) + return 0; + return 1; +} + +static int ssl_get_keyex(const char **pname, SSL *ssl) +{ + unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; + if (alg_k & SSL_kRSA) { + *pname = "rsa"; + return SSL_kRSA; + } + if (alg_k & SSL_kDHr) { + *pname = "dh_rsa"; + return SSL_kDHr; + } + if (alg_k & SSL_kDHd) { + *pname = "dh_dss"; + return SSL_kDHd; + } + if (alg_k & SSL_kKRB5) { + *pname = "krb5"; + return SSL_kKRB5; + } + if (alg_k & SSL_kEDH) { + *pname = "edh"; + return SSL_kEDH; + } + if (alg_k & SSL_kEECDH) { + *pname = "EECDH"; + return SSL_kEECDH; + } + if (alg_k & SSL_kECDHr) { + *pname = "ECDH RSA"; + return SSL_kECDHr; + } + if (alg_k & SSL_kECDHe) { + *pname = "ECDH ECDSA"; + return SSL_kECDHe; + } + if (alg_k & SSL_kPSK) { + *pname = "PSK"; + return SSL_kPSK; + } + if (alg_k & SSL_kSRP) { + *pname = "SRP"; + return SSL_kSRP; + } + if (alg_k & SSL_kGOST) { + *pname = "GOST"; + return SSL_kGOST; + } + *pname = "UNKNOWN"; + return 0; +} + +static int ssl_print_client_keyex(BIO *bio, int indent, SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + const char *algname; + int id; + id = ssl_get_keyex(&algname, ssl); + BIO_indent(bio, indent, 80); + BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname); + switch (id) { + + case SSL_kRSA: + if (TLS1_get_version(ssl) == SSL3_VERSION) { + ssl_print_hex(bio, indent + 2, + "EncyptedPreMasterSecret", msg, msglen); + } else { + if (!ssl_print_hexbuf(bio, indent + 2, + "EncyptedPreMasterSecret", 2, + &msg, &msglen)) + return 0; + } + break; + + /* Implicit parameters only allowed for static DH */ + case SSL_kDHd: + case SSL_kDHr: + if (msglen == 0) { + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "implicit\n"); + break; + } + case SSL_kEDH: + if (!ssl_print_hexbuf(bio, indent + 2, "dh_Yc", 2, &msg, &msglen)) + return 0; + break; + + case SSL_kECDHr: + case SSL_kECDHe: + if (msglen == 0) { + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "implicit\n"); + break; + } + case SSL_kEECDH: + if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen)) + return 0; + break; + } + + return 1; +} + +static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl, + const unsigned char *msg, size_t msglen) +{ + const char *algname; + int id; + id = ssl_get_keyex(&algname, ssl); + BIO_indent(bio, indent, 80); + BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname); + switch (id) { + /* Should never happen */ + case SSL_kDHd: + case SSL_kDHr: + case SSL_kECDHr: + case SSL_kECDHe: + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "Unexpected Message\n"); + break; + + case SSL_kRSA: + + if (!ssl_print_hexbuf(bio, indent + 2, "rsa_modulus", 2, + &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "rsa_exponent", 2, + &msg, &msglen)) + return 0; + break; + + case SSL_kEDH: + if (!ssl_print_hexbuf(bio, indent + 2, "dh_p", 2, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "dh_g", 2, &msg, &msglen)) + return 0; + if (!ssl_print_hexbuf(bio, indent + 2, "dh_Ys", 2, &msg, &msglen)) + return 0; + break; + + case SSL_kEECDH: + if (msglen < 1) + return 0; + BIO_indent(bio, indent + 2, 80); + if (msg[0] == EXPLICIT_PRIME_CURVE_TYPE) + BIO_puts(bio, "explicit_prime\n"); + else if (msg[0] == EXPLICIT_CHAR2_CURVE_TYPE) + BIO_puts(bio, "explicit_char2\n"); + else if (msg[0] == NAMED_CURVE_TYPE) { + int curve; + if (msglen < 3) + return 0; + curve = (msg[1] << 8) | msg[2]; + BIO_printf(bio, "named_curve: %s (%d)\n", + ssl_trace_str(curve, ssl_curve_tbl), curve); + msg += 3; + msglen -= 3; + if (!ssl_print_hexbuf(bio, indent + 2, "point", 1, &msg, &msglen)) + return 0; + } + break; + } + return ssl_print_signature(bio, indent, ssl, &msg, &msglen); +} + +static int ssl_print_certificate(BIO *bio, int indent, + const unsigned char **pmsg, size_t *pmsglen) +{ + size_t msglen = *pmsglen; + size_t clen; + X509 *x; + const unsigned char *p = *pmsg, *q; + if (msglen < 3) + return 0; + clen = (p[0] << 16) | (p[1] << 8) | p[2]; + if (msglen < clen + 3) + return 0; + q = p + 3; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "ASN.1Cert, length=%d", (int)clen); + x = d2i_X509(NULL, &q, clen); + if (!x) + BIO_puts(bio, "<UNPARSEABLE CERTIFICATE>\n"); + else { + BIO_puts(bio, "\n------details-----\n"); + X509_print_ex(bio, x, XN_FLAG_ONELINE, 0); + PEM_write_bio_X509(bio, x); + /* Print certificate stuff */ + BIO_puts(bio, "------------------\n"); + X509_free(x); + } + if (q != p + 3 + clen) { + BIO_puts(bio, "<TRAILING GARBAGE AFTER CERTIFICATE>\n"); + } + *pmsg += clen + 3; + *pmsglen -= clen + 3; + return 1; +} + +static int ssl_print_certificates(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + size_t clen; + if (msglen < 3) + return 0; + clen = (msg[0] << 16) | (msg[1] << 8) | msg[2]; + if (msglen != clen + 3) + return 0; + msg += 3; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "certificate_list, length=%d\n", (int)clen); + while (clen > 0) { + if (!ssl_print_certificate(bio, indent + 2, &msg, &clen)) + return 0; + } + return 1; +} + +static int ssl_print_cert_request(BIO *bio, int indent, SSL *s, + const unsigned char *msg, size_t msglen) +{ + size_t xlen; + if (msglen < 1) + return 0; + xlen = msg[0]; + if (msglen < xlen + 1) + return 0; + msg++; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "certificate_types (len=%d)\n", (int)xlen); + if (!ssl_trace_list(bio, indent + 2, msg, xlen, 1, ssl_ctype_tbl)) + return 0; + msg += xlen; + msglen -= xlen + 1; + if (!SSL_USE_SIGALGS(s)) + goto skip_sig; + if (msglen < 2) + return 0; + xlen = (msg[0] << 8) | msg[1]; + if (msglen < xlen + 2 || (xlen & 1)) + return 0; + msg += 2; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen); + while (xlen > 0) { + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "%s+%s (%d+%d)\n", + ssl_trace_str(msg[0], ssl_md_tbl), + ssl_trace_str(msg[1], ssl_sig_tbl), msg[0], msg[1]); + xlen -= 2; + msg += 2; + } + msg += xlen; + msglen -= xlen + 2; + + skip_sig: + xlen = (msg[0] << 8) | msg[1]; + BIO_indent(bio, indent, 80); + if (msglen < xlen + 2) + return 0; + msg += 2; + msglen -= 2; + BIO_printf(bio, "certificate_authorities (len=%d)\n", (int)xlen); + while (xlen > 0) { + size_t dlen; + X509_NAME *nm; + const unsigned char *p; + if (xlen < 2) + return 0; + dlen = (msg[0] << 8) | msg[1]; + if (xlen < dlen + 2) + return 0; + msg += 2; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "DistinguishedName (len=%d): ", (int)dlen); + p = msg; + nm = d2i_X509_NAME(NULL, &p, dlen); + if (!nm) { + BIO_puts(bio, "<UNPARSEABLE DN>\n"); + } else { + X509_NAME_print_ex(bio, nm, 0, XN_FLAG_ONELINE); + BIO_puts(bio, "\n"); + X509_NAME_free(nm); + } + xlen -= dlen + 2; + msg += dlen; + } + return 1; +} + +static int ssl_print_ticket(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + unsigned int tick_life; + if (msglen == 0) { + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "No Ticket\n"); + return 1; + } + if (msglen < 4) + return 0; + tick_life = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8) | msg[3]; + msglen -= 4; + msg += 4; + BIO_indent(bio, indent + 2, 80); + BIO_printf(bio, "ticket_lifetime_hint=%u\n", tick_life); + if (!ssl_print_hexbuf(bio, indent + 2, "ticket", 2, &msg, &msglen)) + return 0; + if (msglen) + return 0; + return 1; +} + +static int ssl_print_handshake(BIO *bio, SSL *ssl, + const unsigned char *msg, size_t msglen, + int indent) +{ + size_t hlen; + unsigned char htype; + if (msglen < 4) + return 0; + htype = msg[0]; + hlen = (msg[1] << 16) | (msg[2] << 8) | msg[3]; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "%s, Length=%d\n", + ssl_trace_str(htype, ssl_handshake_tbl), (int)hlen); + msg += 4; + msglen -= 4; + if (SSL_IS_DTLS(ssl)) { + if (msglen < 8) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "message_seq=%d, fragment_offset=%d, " + "fragment_length=%d\n", + (msg[0] << 8) | msg[1], + (msg[2] << 16) | (msg[3] << 8) | msg[4], + (msg[5] << 16) | (msg[6] << 8) | msg[7]); + msg += 8; + msglen -= 8; + } + if (msglen < hlen) + return 0; + switch (htype) { + case SSL3_MT_CLIENT_HELLO: + if (!ssl_print_client_hello(bio, ssl, indent + 2, msg, msglen)) + return 0; + break; + + case DTLS1_MT_HELLO_VERIFY_REQUEST: + if (!dtls_print_hello_vfyrequest(bio, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_SERVER_HELLO: + if (!ssl_print_server_hello(bio, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_SERVER_KEY_EXCHANGE: + if (!ssl_print_server_keyex(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_CLIENT_KEY_EXCHANGE: + if (!ssl_print_client_keyex(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE: + if (!ssl_print_certificates(bio, indent + 2, msg, msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE_VERIFY: + if (!ssl_print_signature(bio, indent + 2, ssl, &msg, &msglen)) + return 0; + break; + + case SSL3_MT_CERTIFICATE_REQUEST: + if (!ssl_print_cert_request(bio, indent + 2, ssl, msg, msglen)) + return 0; + break; + + case SSL3_MT_FINISHED: + ssl_print_hex(bio, indent + 2, "verify_data", msg, msglen); + break; + + case SSL3_MT_SERVER_DONE: + if (msglen != 0) + ssl_print_hex(bio, indent + 2, "unexpected value", msg, msglen); + break; + + case SSL3_MT_NEWSESSION_TICKET: + if (!ssl_print_ticket(bio, indent + 2, msg, msglen)) + return 0; + break; + + default: + BIO_indent(bio, indent + 2, 80); + BIO_puts(bio, "Unsupported, hex dump follows:\n"); + BIO_dump_indent(bio, (char *)msg, msglen, indent + 4); + } + return 1; +} + +static int ssl_print_heartbeat(BIO *bio, int indent, + const unsigned char *msg, size_t msglen) +{ + if (msglen < 3) + return 0; + BIO_indent(bio, indent, 80); + BIO_printf(bio, "HeartBeatMessageType: %s\n", + ssl_trace_str(msg[0], ssl_hb_type_tbl)); + msg++; + msglen--; + if (!ssl_print_hexbuf(bio, indent, "payload", 2, &msg, &msglen)) + return 0; + ssl_print_hex(bio, indent, "padding", msg, msglen); + return 1; +} + +const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c) +{ + if (c->algorithm_ssl & SSL_SSLV2) + return NULL; + return ssl_trace_str(c->id & 0xFFFF, ssl_ciphers_tbl); +} + +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t msglen, SSL *ssl, void *arg) +{ + const unsigned char *msg = buf; + BIO *bio = arg; + + if (write_p == 2) { + BIO_puts(bio, "Session "); + ssl_print_hex(bio, 0, + ssl_trace_str(content_type, ssl_crypto_tbl), + msg, msglen); + return; + } + switch (content_type) { + case SSL3_RT_HEADER: + { + int hvers = msg[1] << 8 | msg[2]; + BIO_puts(bio, write_p ? "Sent" : "Received"); + BIO_printf(bio, " Record\nHeader:\n Version = %s (0x%x)\n", + ssl_trace_str(hvers, ssl_version_tbl), hvers); + if (SSL_IS_DTLS(ssl)) { + BIO_printf(bio, + " epoch=%d, sequence_number=%04x%04x%04x\n", + (msg[3] << 8 | msg[4]), + (msg[5] << 8 | msg[6]), + (msg[7] << 8 | msg[8]), (msg[9] << 8 | msg[10])); +# if 0 + /* + * Just print handshake type so we can see what is going on + * during fragmentation. + */ + BIO_printf(bio, "(%s)\n", + ssl_trace_str(msg[msglen], ssl_handshake_tbl)); +# endif + } + + BIO_printf(bio, " Content Type = %s (%d)\n Length = %d", + ssl_trace_str(msg[0], ssl_content_tbl), msg[0], + msg[msglen - 2] << 8 | msg[msglen - 1]); + } + break; + case SSL3_RT_HANDSHAKE: + if (!ssl_print_handshake(bio, ssl, msg, msglen, 4)) + BIO_printf(bio, "Message length parse error!\n"); + break; + + case SSL3_RT_CHANGE_CIPHER_SPEC: + if (msglen == 1 && msg[0] == 1) + BIO_puts(bio, " change_cipher_spec (1)\n"); + else + ssl_print_hex(bio, 4, "unknown value", msg, msglen); + break; + + case SSL3_RT_ALERT: + if (msglen != 2) + BIO_puts(bio, " Illegal Alert Length\n"); + else { + BIO_printf(bio, " Level=%s(%d), description=%s(%d)\n", + SSL_alert_type_string_long(msg[0] << 8), + msg[0], SSL_alert_desc_string_long(msg[1]), msg[1]); + } + case TLS1_RT_HEARTBEAT: + ssl_print_heartbeat(bio, 4, msg, msglen); + break; + + } + + BIO_puts(bio, "\n"); +} + +#endif diff --git a/ssl/tls1.h b/ssl/tls1.h index 69d8186a4e24..5929607ff8b6 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -209,11 +209,9 @@ extern "C" { # define TLSEXT_TYPE_status_request 5 /* ExtensionType values from RFC4681 */ # define TLSEXT_TYPE_user_mapping 6 - /* ExtensionType values from RFC5878 */ # define TLSEXT_TYPE_client_authz 7 # define TLSEXT_TYPE_server_authz 8 - /* ExtensionType values from RFC6091 */ # define TLSEXT_TYPE_cert_type 9 @@ -233,6 +231,9 @@ extern "C" { /* ExtensionType value from RFC5620 */ # define TLSEXT_TYPE_heartbeat 15 +/* ExtensionType value from draft-ietf-tls-applayerprotoneg-00 */ +# define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + /* * ExtensionType value for TLS padding extension. * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml @@ -250,7 +251,7 @@ extern "C" { * i.e. build with -DTLSEXT_TYPE_opaque_prf_input=38183 * using whatever extension number you'd like to try */ -# define TLSEXT_TYPE_opaque_prf_input ?? */ +# define TLSEXT_TYPE_opaque_prf_input ?? # endif /* Temporary extension type */ @@ -280,6 +281,9 @@ extern "C" { # define TLSEXT_signature_dsa 2 # define TLSEXT_signature_ecdsa 3 +/* Total number of different signature algorithms */ +# define TLSEXT_signature_num 4 + # define TLSEXT_hash_none 0 # define TLSEXT_hash_md5 1 # define TLSEXT_hash_sha1 2 @@ -288,6 +292,18 @@ extern "C" { # define TLSEXT_hash_sha384 5 # define TLSEXT_hash_sha512 6 +/* Total number of different digest algorithms */ + +# define TLSEXT_hash_num 7 + +/* Flag set for unrecognised algorithms */ +# define TLSEXT_nid_unknown 0x1000000 + +/* ECC curves */ + +# define TLSEXT_curve_P_256 23 +# define TLSEXT_curve_P_384 24 + # ifndef OPENSSL_NO_TLSEXT # define TLSEXT_MAXLEN_host_name 255 @@ -306,6 +322,16 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, const unsigned char *p, size_t plen, int use_context); +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain); + # define SSL_set_tlsext_host_name(s,name) \ SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) @@ -541,11 +567,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) # define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 /* - * XXX Inconsistency alert: The OpenSSL names of ciphers with ephemeral DH - * here include the string "DHE", while elsewhere it has always been "EDH". - * (The alias for the list of all such ciphers also is "EDH".) The - * specifications speak of "EDH"; maybe we should allow both forms for - * everything. + * XXX * Backward compatibility alert: + * Older versions of OpenSSL gave + * some DHE ciphers names with "EDH" + * instead of "DHE". Going forward, we + * should be using DHE + * everywhere, though we may indefinitely maintain + * aliases for users + * or configurations that used "EDH" + */ # define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" # define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" |