From 499684404ccf27b261cd72770c068fee4ea6f369 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 1 Dec 2009 17:42:15 +0000 Subject: PR: 2115 Submitted by: Robin Seggelmann Approved by: steve@openssl.org Add Renegotiation extension to DTLS, fix DTLS ClientHello processing bug. --- ssl/d1_lib.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) (limited to 'ssl/d1_lib.c') diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 2786b61c29..99935563d1 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -382,3 +382,194 @@ int dtls1_listen(SSL *s, struct sockaddr *client) (void) BIO_dgram_get_peer(SSL_get_rbio(s), client); return 1; } + +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_clienthello_dtlsext(SSL *s, unsigned char *p, unsigned char *limit) + { + int extdatalen = 0; + unsigned char *ret = p; + int el; + + ret+=2; + + if (ret>=limit) return NULL; /* this really never occurs, but ... */ + + /* Renegotiate extension */ + if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + + if ((extdatalen = ret-p-2)== 0) + return p; + + s2n(extdatalen,p); + + return ret; + } + +int ssl_parse_clienthello_dtlsext(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; + + if (data >= (d+n-2)) + { + if (s->new_session + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + /* We should always see one extension: the renegotiate extension */ + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } + return 1; + } + n2s(data,len); + + if (data > (d+n-len)) + return 1; + + while (data <= (d+n-4)) + { + n2s(data,type); + n2s(data,size); + + if (data+size > (d+n)) + return 1; + + if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } + + data+=size; + } + + if (s->new_session && !renegotiate_seen + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + *p = data; + return 1; + } + +unsigned char *ssl_add_serverhello_dtlsext(SSL *s, unsigned char *p, unsigned char *limit) + { + int extdatalen = 0; + unsigned char *ret = p; + + ret+=2; + + if (ret>=limit) return NULL; /* this really never occurs, but ... */ + + if(s->s3->send_connection_binding) + { + int el; + + if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) + { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + } + + if ((extdatalen = ret-p-2)== 0) + return p; + + s2n(extdatalen,p); + + return ret; + } + +int ssl_parse_serverhello_dtlsext(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; + + if (data >= (d+n-2)) + { + if (s->new_session + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + /* We should always see one extension: the renegotiate extension */ + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } + return 1; + } + n2s(data,len); + + if (data > (d+n-len)) + return 1; + + while (data <= (d+n-4)) + { + n2s(data,type); + n2s(data,size); + + if (data+size > (d+n)) + return 1; + + if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } + + data+=size; + } + + if (s->new_session && !renegotiate_seen + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + *p = data; + return 1; + } +#endif -- cgit v1.2.3