aboutsummaryrefslogtreecommitdiff
path: root/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'ssl')
-rw-r--r--ssl/Makefile101
-rw-r--r--ssl/d1_both.c142
-rw-r--r--ssl/d1_clnt.c918
-rw-r--r--ssl/d1_enc.c251
-rw-r--r--ssl/d1_lib.c92
-rw-r--r--ssl/d1_meth.c18
-rw-r--r--ssl/d1_pkt.c66
-rw-r--r--ssl/d1_srtp.c3
-rw-r--r--ssl/d1_srvr.c903
-rw-r--r--ssl/dtls1.h6
-rw-r--r--ssl/heartbeat_test.c38
-rw-r--r--ssl/s23_clnt.c24
-rw-r--r--ssl/s23_srvr.c5
-rw-r--r--ssl/s2_clnt.c16
-rw-r--r--ssl/s2_lib.c5
-rw-r--r--ssl/s3_both.c119
-rw-r--r--ssl/s3_cbc.c2
-rw-r--r--ssl/s3_clnt.c466
-rw-r--r--ssl/s3_enc.c36
-rw-r--r--ssl/s3_lib.c656
-rw-r--r--ssl/s3_pkt.c198
-rw-r--r--ssl/s3_srvr.c455
-rw-r--r--ssl/srtp.h1
-rw-r--r--ssl/ssl.h422
-rw-r--r--ssl/ssl3.h62
-rw-r--r--ssl/ssl_algs.c4
-rw-r--r--ssl/ssl_cert.c544
-rw-r--r--ssl/ssl_ciph.c181
-rw-r--r--ssl/ssl_conf.c683
-rw-r--r--ssl/ssl_err.c267
-rw-r--r--ssl/ssl_lib.c431
-rw-r--r--ssl/ssl_locl.h316
-rw-r--r--ssl/ssl_rsa.c292
-rw-r--r--ssl/ssl_sess.c35
-rw-r--r--ssl/ssl_txt.c2
-rw-r--r--ssl/ssltest.c566
-rw-r--r--ssl/t1_clnt.c8
-rw-r--r--ssl/t1_enc.c68
-rw-r--r--ssl/t1_ext.c298
-rw-r--r--ssl/t1_lib.c2223
-rw-r--r--ssl/t1_meth.c9
-rw-r--r--ssl/t1_srvr.c9
-rw-r--r--ssl/t1_trce.c1266
-rw-r--r--ssl/tls1.h41
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"