aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'ssl')
-rw-r--r--ssl/bio_ssl.c982
-rw-r--r--ssl/d1_both.c2855
-rw-r--r--ssl/d1_clnt.c2912
-rw-r--r--ssl/d1_enc.c240
-rw-r--r--ssl/d1_lib.c724
-rw-r--r--ssl/d1_meth.c23
-rw-r--r--ssl/d1_pkt.c3199
-rw-r--r--ssl/d1_srtp.c658
-rw-r--r--ssl/d1_srvr.c2958
-rw-r--r--ssl/dtls1.h394
-rw-r--r--ssl/heartbeat_test.c762
-rw-r--r--ssl/kssl.c3921
-rw-r--r--ssl/kssl.h203
-rw-r--r--ssl/kssl_lcl.h19
-rw-r--r--ssl/s23_clnt.c1257
-rw-r--r--ssl/s23_lib.c211
-rw-r--r--ssl/s23_meth.c49
-rw-r--r--ssl/s23_pkt.c96
-rw-r--r--ssl/s23_srvr.c1027
-rw-r--r--ssl/s2_clnt.c1929
-rw-r--r--ssl/s2_enc.c266
-rw-r--r--ssl/s2_lib.c769
-rw-r--r--ssl/s2_meth.c37
-rw-r--r--ssl/s2_pkt.c1183
-rw-r--r--ssl/s2_srvr.c2021
-rw-r--r--ssl/s3_both.c1254
-rw-r--r--ssl/s3_cbc.c1242
-rw-r--r--ssl/s3_clnt.c6142
-rw-r--r--ssl/s3_enc.c1421
-rw-r--r--ssl/s3_lib.c7729
-rw-r--r--ssl/s3_meth.c28
-rw-r--r--ssl/s3_pkt.c2726
-rw-r--r--ssl/s3_srvr.c6527
-rw-r--r--ssl/srtp.h45
-rw-r--r--ssl/ssl.h4407
-rw-r--r--ssl/ssl2.h359
-rw-r--r--ssl/ssl23.h33
-rw-r--r--ssl/ssl3.h1100
-rw-r--r--ssl/ssl_algs.c121
-rw-r--r--ssl/ssl_asn1.c1007
-rw-r--r--ssl/ssl_cert.c1111
-rw-r--r--ssl/ssl_ciph.c3251
-rw-r--r--ssl/ssl_err.c1254
-rw-r--r--ssl/ssl_err2.c21
-rw-r--r--ssl/ssl_lib.c5360
-rw-r--r--ssl/ssl_locl.h1521
-rw-r--r--ssl/ssl_rsa.c1267
-rw-r--r--ssl/ssl_sess.c1785
-rw-r--r--ssl/ssl_stat.c1370
-rw-r--r--ssl/ssl_task.c376
-rw-r--r--ssl/ssl_txt.c302
-rw-r--r--ssl/ssl_utst.c25
-rw-r--r--ssl/ssltest.c4373
-rw-r--r--ssl/t1_clnt.c50
-rw-r--r--ssl/t1_enc.c2113
-rw-r--r--ssl/t1_lib.c4910
-rw-r--r--ssl/t1_meth.c47
-rw-r--r--ssl/t1_reneg.c226
-rw-r--r--ssl/t1_srvr.c50
-rw-r--r--ssl/tls1.h954
-rw-r--r--ssl/tls_srp.c878
61 files changed, 47199 insertions, 46881 deletions
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
index e9552caee2aa..a0c583e34215 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -5,21 +5,21 @@
* 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:
@@ -34,10 +34,10 @@
* 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
+ * 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
@@ -49,7 +49,7 @@
* 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
@@ -72,534 +72,516 @@ static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int ssl_new(BIO *h);
static int ssl_free(BIO *data);
static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
-typedef struct bio_ssl_st
- {
- SSL *ssl; /* The ssl handle :-) */
- /* re-negotiate every time the total number of bytes is this size */
- int num_renegotiates;
- unsigned long renegotiate_count;
- unsigned long byte_count;
- unsigned long renegotiate_timeout;
- unsigned long last_time;
- } BIO_SSL;
-
-static BIO_METHOD methods_sslp=
- {
- BIO_TYPE_SSL,"ssl",
- ssl_write,
- ssl_read,
- ssl_puts,
- NULL, /* ssl_gets, */
- ssl_ctrl,
- ssl_new,
- ssl_free,
- ssl_callback_ctrl,
- };
+typedef struct bio_ssl_st {
+ SSL *ssl; /* The ssl handle :-) */
+ /* re-negotiate every time the total number of bytes is this size */
+ int num_renegotiates;
+ unsigned long renegotiate_count;
+ unsigned long byte_count;
+ unsigned long renegotiate_timeout;
+ unsigned long last_time;
+} BIO_SSL;
+
+static BIO_METHOD methods_sslp = {
+ BIO_TYPE_SSL, "ssl",
+ ssl_write,
+ ssl_read,
+ ssl_puts,
+ NULL, /* ssl_gets, */
+ ssl_ctrl,
+ ssl_new,
+ ssl_free,
+ ssl_callback_ctrl,
+};
BIO_METHOD *BIO_f_ssl(void)
- {
- return(&methods_sslp);
- }
+{
+ return (&methods_sslp);
+}
static int ssl_new(BIO *bi)
- {
- BIO_SSL *bs;
-
- bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL));
- if (bs == NULL)
- {
- BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- memset(bs,0,sizeof(BIO_SSL));
- bi->init=0;
- bi->ptr=(char *)bs;
- bi->flags=0;
- return(1);
- }
+{
+ BIO_SSL *bs;
+
+ bs = (BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL));
+ if (bs == NULL) {
+ BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+ memset(bs, 0, sizeof(BIO_SSL));
+ bi->init = 0;
+ bi->ptr = (char *)bs;
+ bi->flags = 0;
+ return (1);
+}
static int ssl_free(BIO *a)
- {
- BIO_SSL *bs;
-
- if (a == NULL) return(0);
- bs=(BIO_SSL *)a->ptr;
- if (bs->ssl != NULL) SSL_shutdown(bs->ssl);
- if (a->shutdown)
- {
- if (a->init && (bs->ssl != NULL))
- SSL_free(bs->ssl);
- a->init=0;
- a->flags=0;
- }
- if (a->ptr != NULL)
- OPENSSL_free(a->ptr);
- return(1);
- }
-
+{
+ BIO_SSL *bs;
+
+ if (a == NULL)
+ return (0);
+ bs = (BIO_SSL *)a->ptr;
+ if (bs->ssl != NULL)
+ SSL_shutdown(bs->ssl);
+ if (a->shutdown) {
+ if (a->init && (bs->ssl != NULL))
+ SSL_free(bs->ssl);
+ a->init = 0;
+ a->flags = 0;
+ }
+ if (a->ptr != NULL)
+ OPENSSL_free(a->ptr);
+ return (1);
+}
+
static int ssl_read(BIO *b, char *out, int outl)
- {
- int ret=1;
- BIO_SSL *sb;
- SSL *ssl;
- int retry_reason=0;
- int r=0;
+{
+ int ret = 1;
+ BIO_SSL *sb;
+ SSL *ssl;
+ int retry_reason = 0;
+ int r = 0;
- if (out == NULL) return(0);
- sb=(BIO_SSL *)b->ptr;
- ssl=sb->ssl;
+ if (out == NULL)
+ return (0);
+ sb = (BIO_SSL *)b->ptr;
+ ssl = sb->ssl;
- BIO_clear_retry_flags(b);
+ BIO_clear_retry_flags(b);
#if 0
- if (!SSL_is_init_finished(ssl))
- {
-/* ret=SSL_do_handshake(ssl); */
- if (ret > 0)
- {
-
- outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
- ret= -1;
- goto end;
- }
- }
+ if (!SSL_is_init_finished(ssl)) {
+/* ret=SSL_do_handshake(ssl); */
+ if (ret > 0) {
+
+ outflags = (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
+ ret = -1;
+ goto end;
+ }
+ }
#endif
-/* if (ret > 0) */
- ret=SSL_read(ssl,out,outl);
-
- switch (SSL_get_error(ssl,ret))
- {
- case SSL_ERROR_NONE:
- if (ret <= 0) break;
- if (sb->renegotiate_count > 0)
- {
- sb->byte_count+=ret;
- if (sb->byte_count > sb->renegotiate_count)
- {
- sb->byte_count=0;
- sb->num_renegotiates++;
- SSL_renegotiate(ssl);
- r=1;
- }
- }
- if ((sb->renegotiate_timeout > 0) && (!r))
- {
- unsigned long tm;
-
- tm=(unsigned long)time(NULL);
- if (tm > sb->last_time+sb->renegotiate_timeout)
- {
- sb->last_time=tm;
- sb->num_renegotiates++;
- SSL_renegotiate(ssl);
- }
- }
-
- break;
- case SSL_ERROR_WANT_READ:
- BIO_set_retry_read(b);
- break;
- case SSL_ERROR_WANT_WRITE:
- BIO_set_retry_write(b);
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- BIO_set_retry_special(b);
- retry_reason=BIO_RR_SSL_X509_LOOKUP;
- break;
- case SSL_ERROR_WANT_ACCEPT:
- BIO_set_retry_special(b);
- retry_reason=BIO_RR_ACCEPT;
- break;
- case SSL_ERROR_WANT_CONNECT:
- BIO_set_retry_special(b);
- retry_reason=BIO_RR_CONNECT;
- break;
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- case SSL_ERROR_ZERO_RETURN:
- default:
- break;
- }
-
- b->retry_reason=retry_reason;
- return(ret);
- }
+/* if (ret > 0) */
+ ret = SSL_read(ssl, out, outl);
+
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_NONE:
+ if (ret <= 0)
+ break;
+ if (sb->renegotiate_count > 0) {
+ sb->byte_count += ret;
+ if (sb->byte_count > sb->renegotiate_count) {
+ sb->byte_count = 0;
+ sb->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ r = 1;
+ }
+ }
+ if ((sb->renegotiate_timeout > 0) && (!r)) {
+ unsigned long tm;
+
+ tm = (unsigned long)time(NULL);
+ if (tm > sb->last_time + sb->renegotiate_timeout) {
+ sb->last_time = tm;
+ sb->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ }
+ }
+
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_set_retry_read(b);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_retry_write(b);
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_SSL_X509_LOOKUP;
+ break;
+ case SSL_ERROR_WANT_ACCEPT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_ACCEPT;
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_CONNECT;
+ break;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ case SSL_ERROR_ZERO_RETURN:
+ default:
+ break;
+ }
+
+ b->retry_reason = retry_reason;
+ return (ret);
+}
static int ssl_write(BIO *b, const char *out, int outl)
- {
- int ret,r=0;
- int retry_reason=0;
- SSL *ssl;
- BIO_SSL *bs;
-
- if (out == NULL) return(0);
- bs=(BIO_SSL *)b->ptr;
- ssl=bs->ssl;
-
- BIO_clear_retry_flags(b);
-
-/* ret=SSL_do_handshake(ssl);
- if (ret > 0) */
- ret=SSL_write(ssl,out,outl);
-
- switch (SSL_get_error(ssl,ret))
- {
- case SSL_ERROR_NONE:
- if (ret <= 0) break;
- if (bs->renegotiate_count > 0)
- {
- bs->byte_count+=ret;
- if (bs->byte_count > bs->renegotiate_count)
- {
- bs->byte_count=0;
- bs->num_renegotiates++;
- SSL_renegotiate(ssl);
- r=1;
- }
- }
- if ((bs->renegotiate_timeout > 0) && (!r))
- {
- unsigned long tm;
-
- tm=(unsigned long)time(NULL);
- if (tm > bs->last_time+bs->renegotiate_timeout)
- {
- bs->last_time=tm;
- bs->num_renegotiates++;
- SSL_renegotiate(ssl);
- }
- }
- break;
- case SSL_ERROR_WANT_WRITE:
- BIO_set_retry_write(b);
- break;
- case SSL_ERROR_WANT_READ:
- BIO_set_retry_read(b);
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- BIO_set_retry_special(b);
- retry_reason=BIO_RR_SSL_X509_LOOKUP;
- break;
- case SSL_ERROR_WANT_CONNECT:
- BIO_set_retry_special(b);
- retry_reason=BIO_RR_CONNECT;
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- default:
- break;
- }
-
- b->retry_reason=retry_reason;
- return(ret);
- }
+{
+ int ret, r = 0;
+ int retry_reason = 0;
+ SSL *ssl;
+ BIO_SSL *bs;
+
+ if (out == NULL)
+ return (0);
+ bs = (BIO_SSL *)b->ptr;
+ ssl = bs->ssl;
+
+ BIO_clear_retry_flags(b);
+
+ /*
+ * ret=SSL_do_handshake(ssl); if (ret > 0)
+ */
+ ret = SSL_write(ssl, out, outl);
+
+ switch (SSL_get_error(ssl, ret)) {
+ case SSL_ERROR_NONE:
+ if (ret <= 0)
+ break;
+ if (bs->renegotiate_count > 0) {
+ bs->byte_count += ret;
+ if (bs->byte_count > bs->renegotiate_count) {
+ bs->byte_count = 0;
+ bs->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ r = 1;
+ }
+ }
+ if ((bs->renegotiate_timeout > 0) && (!r)) {
+ unsigned long tm;
+
+ tm = (unsigned long)time(NULL);
+ if (tm > bs->last_time + bs->renegotiate_timeout) {
+ bs->last_time = tm;
+ bs->num_renegotiates++;
+ SSL_renegotiate(ssl);
+ }
+ }
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_retry_write(b);
+ break;
+ case SSL_ERROR_WANT_READ:
+ BIO_set_retry_read(b);
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_SSL_X509_LOOKUP;
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_retry_special(b);
+ retry_reason = BIO_RR_CONNECT;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ default:
+ break;
+ }
+
+ b->retry_reason = retry_reason;
+ return (ret);
+}
static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
- {
- SSL **sslp,*ssl;
- BIO_SSL *bs;
- BIO *dbio,*bio;
- long ret=1;
-
- bs=(BIO_SSL *)b->ptr;
- ssl=bs->ssl;
- if ((ssl == NULL) && (cmd != BIO_C_SET_SSL))
- return(0);
- switch (cmd)
- {
- case BIO_CTRL_RESET:
- SSL_shutdown(ssl);
-
- if (ssl->handshake_func == ssl->method->ssl_connect)
- SSL_set_connect_state(ssl);
- else if (ssl->handshake_func == ssl->method->ssl_accept)
- SSL_set_accept_state(ssl);
-
- SSL_clear(ssl);
-
- if (b->next_bio != NULL)
- ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
- else if (ssl->rbio != NULL)
- ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
- else
- ret=1;
- break;
- case BIO_CTRL_INFO:
- ret=0;
- break;
- case BIO_C_SSL_MODE:
- if (num) /* client mode */
- SSL_set_connect_state(ssl);
- else
- SSL_set_accept_state(ssl);
- break;
- case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
- ret=bs->renegotiate_timeout;
- if (num < 60) num=5;
- bs->renegotiate_timeout=(unsigned long)num;
- bs->last_time=(unsigned long)time(NULL);
- break;
- case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
- ret=bs->renegotiate_count;
- if ((long)num >=512)
- bs->renegotiate_count=(unsigned long)num;
- break;
- case BIO_C_GET_SSL_NUM_RENEGOTIATES:
- ret=bs->num_renegotiates;
- break;
- case BIO_C_SET_SSL:
- if (ssl != NULL)
- {
- ssl_free(b);
- if (!ssl_new(b))
- return 0;
- }
- b->shutdown=(int)num;
- ssl=(SSL *)ptr;
- ((BIO_SSL *)b->ptr)->ssl=ssl;
- bio=SSL_get_rbio(ssl);
- if (bio != NULL)
- {
- if (b->next_bio != NULL)
- BIO_push(bio,b->next_bio);
- b->next_bio=bio;
- CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO);
- }
- b->init=1;
- break;
- case BIO_C_GET_SSL:
- if (ptr != NULL)
- {
- sslp=(SSL **)ptr;
- *sslp=ssl;
- }
- else
- ret=0;
- break;
- case BIO_CTRL_GET_CLOSE:
- ret=b->shutdown;
- break;
- case BIO_CTRL_SET_CLOSE:
- b->shutdown=(int)num;
- break;
- case BIO_CTRL_WPENDING:
- ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);
- break;
- case BIO_CTRL_PENDING:
- ret=SSL_pending(ssl);
- if (ret == 0)
- ret=BIO_pending(ssl->rbio);
- break;
- case BIO_CTRL_FLUSH:
- BIO_clear_retry_flags(b);
- ret=BIO_ctrl(ssl->wbio,cmd,num,ptr);
- BIO_copy_next_retry(b);
- break;
- case BIO_CTRL_PUSH:
- if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio))
- {
- SSL_set_bio(ssl,b->next_bio,b->next_bio);
- CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO);
- }
- break;
- case BIO_CTRL_POP:
- /* Only detach if we are the BIO explicitly being popped */
- if (b == ptr)
- {
- /* Shouldn't happen in practice because the
- * rbio and wbio are the same when pushed.
- */
- if (ssl->rbio != ssl->wbio)
- BIO_free_all(ssl->wbio);
- if (b->next_bio != NULL)
- CRYPTO_add(&b->next_bio->references,-1,CRYPTO_LOCK_BIO);
- ssl->wbio=NULL;
- ssl->rbio=NULL;
- }
- break;
- case BIO_C_DO_STATE_MACHINE:
- BIO_clear_retry_flags(b);
-
- b->retry_reason=0;
- ret=(int)SSL_do_handshake(ssl);
-
- switch (SSL_get_error(ssl,(int)ret))
- {
- case SSL_ERROR_WANT_READ:
- BIO_set_flags(b,
- BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
- break;
- case SSL_ERROR_WANT_WRITE:
- BIO_set_flags(b,
- BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
- break;
- case SSL_ERROR_WANT_CONNECT:
- BIO_set_flags(b,
- BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
- b->retry_reason=b->next_bio->retry_reason;
- break;
- default:
- break;
- }
- break;
- case BIO_CTRL_DUP:
- dbio=(BIO *)ptr;
- if (((BIO_SSL *)dbio->ptr)->ssl != NULL)
- SSL_free(((BIO_SSL *)dbio->ptr)->ssl);
- ((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl);
- ((BIO_SSL *)dbio->ptr)->renegotiate_count=
- ((BIO_SSL *)b->ptr)->renegotiate_count;
- ((BIO_SSL *)dbio->ptr)->byte_count=
- ((BIO_SSL *)b->ptr)->byte_count;
- ((BIO_SSL *)dbio->ptr)->renegotiate_timeout=
- ((BIO_SSL *)b->ptr)->renegotiate_timeout;
- ((BIO_SSL *)dbio->ptr)->last_time=
- ((BIO_SSL *)b->ptr)->last_time;
- ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL);
- break;
- case BIO_C_GET_FD:
- ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
- break;
- case BIO_CTRL_SET_CALLBACK:
- {
-#if 0 /* FIXME: Should this be used? -- Richard Levitte */
- SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- ret = -1;
+{
+ SSL **sslp, *ssl;
+ BIO_SSL *bs;
+ BIO *dbio, *bio;
+ long ret = 1;
+
+ bs = (BIO_SSL *)b->ptr;
+ ssl = bs->ssl;
+ if ((ssl == NULL) && (cmd != BIO_C_SET_SSL))
+ return (0);
+ switch (cmd) {
+ case BIO_CTRL_RESET:
+ SSL_shutdown(ssl);
+
+ if (ssl->handshake_func == ssl->method->ssl_connect)
+ SSL_set_connect_state(ssl);
+ else if (ssl->handshake_func == ssl->method->ssl_accept)
+ SSL_set_accept_state(ssl);
+
+ SSL_clear(ssl);
+
+ if (b->next_bio != NULL)
+ ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+ else if (ssl->rbio != NULL)
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ else
+ ret = 1;
+ break;
+ case BIO_CTRL_INFO:
+ ret = 0;
+ break;
+ case BIO_C_SSL_MODE:
+ if (num) /* client mode */
+ SSL_set_connect_state(ssl);
+ else
+ SSL_set_accept_state(ssl);
+ break;
+ case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
+ ret = bs->renegotiate_timeout;
+ if (num < 60)
+ num = 5;
+ bs->renegotiate_timeout = (unsigned long)num;
+ bs->last_time = (unsigned long)time(NULL);
+ break;
+ case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
+ ret = bs->renegotiate_count;
+ if ((long)num >= 512)
+ bs->renegotiate_count = (unsigned long)num;
+ break;
+ case BIO_C_GET_SSL_NUM_RENEGOTIATES:
+ ret = bs->num_renegotiates;
+ break;
+ case BIO_C_SET_SSL:
+ if (ssl != NULL) {
+ ssl_free(b);
+ if (!ssl_new(b))
+ return 0;
+ }
+ b->shutdown = (int)num;
+ ssl = (SSL *)ptr;
+ ((BIO_SSL *)b->ptr)->ssl = ssl;
+ bio = SSL_get_rbio(ssl);
+ if (bio != NULL) {
+ if (b->next_bio != NULL)
+ BIO_push(bio, b->next_bio);
+ b->next_bio = bio;
+ CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
+ }
+ b->init = 1;
+ break;
+ case BIO_C_GET_SSL:
+ if (ptr != NULL) {
+ sslp = (SSL **)ptr;
+ *sslp = ssl;
+ } else
+ ret = 0;
+ break;
+ case BIO_CTRL_GET_CLOSE:
+ ret = b->shutdown;
+ break;
+ case BIO_CTRL_SET_CLOSE:
+ b->shutdown = (int)num;
+ break;
+ case BIO_CTRL_WPENDING:
+ ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
+ break;
+ case BIO_CTRL_PENDING:
+ ret = SSL_pending(ssl);
+ if (ret == 0)
+ ret = BIO_pending(ssl->rbio);
+ break;
+ case BIO_CTRL_FLUSH:
+ BIO_clear_retry_flags(b);
+ ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
+ BIO_copy_next_retry(b);
+ break;
+ case BIO_CTRL_PUSH:
+ if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) {
+ SSL_set_bio(ssl, b->next_bio, b->next_bio);
+ CRYPTO_add(&b->next_bio->references, 1, CRYPTO_LOCK_BIO);
+ }
+ break;
+ case BIO_CTRL_POP:
+ /* Only detach if we are the BIO explicitly being popped */
+ if (b == ptr) {
+ /*
+ * Shouldn't happen in practice because the rbio and wbio are the
+ * same when pushed.
+ */
+ if (ssl->rbio != ssl->wbio)
+ BIO_free_all(ssl->wbio);
+ if (b->next_bio != NULL)
+ CRYPTO_add(&b->next_bio->references, -1, CRYPTO_LOCK_BIO);
+ ssl->wbio = NULL;
+ ssl->rbio = NULL;
+ }
+ break;
+ case BIO_C_DO_STATE_MACHINE:
+ BIO_clear_retry_flags(b);
+
+ b->retry_reason = 0;
+ ret = (int)SSL_do_handshake(ssl);
+
+ switch (SSL_get_error(ssl, (int)ret)) {
+ case SSL_ERROR_WANT_READ:
+ BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
+ b->retry_reason = b->next_bio->retry_reason;
+ break;
+ default:
+ break;
+ }
+ break;
+ case BIO_CTRL_DUP:
+ dbio = (BIO *)ptr;
+ if (((BIO_SSL *)dbio->ptr)->ssl != NULL)
+ SSL_free(((BIO_SSL *)dbio->ptr)->ssl);
+ ((BIO_SSL *)dbio->ptr)->ssl = SSL_dup(ssl);
+ ((BIO_SSL *)dbio->ptr)->renegotiate_count =
+ ((BIO_SSL *)b->ptr)->renegotiate_count;
+ ((BIO_SSL *)dbio->ptr)->byte_count = ((BIO_SSL *)b->ptr)->byte_count;
+ ((BIO_SSL *)dbio->ptr)->renegotiate_timeout =
+ ((BIO_SSL *)b->ptr)->renegotiate_timeout;
+ ((BIO_SSL *)dbio->ptr)->last_time = ((BIO_SSL *)b->ptr)->last_time;
+ ret = (((BIO_SSL *)dbio->ptr)->ssl != NULL);
+ break;
+ case BIO_C_GET_FD:
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ break;
+ case BIO_CTRL_SET_CALLBACK:
+ {
+#if 0 /* FIXME: Should this be used? -- Richard
+ * Levitte */
+ SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ret = -1;
#else
- ret=0;
+ ret = 0;
#endif
- }
- break;
- case BIO_CTRL_GET_CALLBACK:
- {
- void (**fptr)(const SSL *xssl,int type,int val);
-
- fptr=(void (**)(const SSL *xssl,int type,int val))ptr;
- *fptr=SSL_get_info_callback(ssl);
- }
- break;
- default:
- ret=BIO_ctrl(ssl->rbio,cmd,num,ptr);
- break;
- }
- return(ret);
- }
+ }
+ break;
+ case BIO_CTRL_GET_CALLBACK:
+ {
+ void (**fptr) (const SSL *xssl, int type, int val);
+
+ fptr = (void (**)(const SSL *xssl, int type, int val))ptr;
+ *fptr = SSL_get_info_callback(ssl);
+ }
+ break;
+ default:
+ ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
+ break;
+ }
+ return (ret);
+}
static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
- {
- SSL *ssl;
- BIO_SSL *bs;
- long ret=1;
-
- bs=(BIO_SSL *)b->ptr;
- ssl=bs->ssl;
- switch (cmd)
- {
- case BIO_CTRL_SET_CALLBACK:
- {
- /* FIXME: setting this via a completely different prototype
- seems like a crap idea */
- SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp);
- }
- break;
- default:
- ret=BIO_callback_ctrl(ssl->rbio,cmd,fp);
- break;
- }
- return(ret);
- }
+{
+ SSL *ssl;
+ BIO_SSL *bs;
+ long ret = 1;
+
+ bs = (BIO_SSL *)b->ptr;
+ ssl = bs->ssl;
+ switch (cmd) {
+ case BIO_CTRL_SET_CALLBACK:
+ {
+ /*
+ * FIXME: setting this via a completely different prototype seems
+ * like a crap idea
+ */
+ SSL_set_info_callback(ssl, (void (*)(const SSL *, int, int))fp);
+ }
+ break;
+ default:
+ ret = BIO_callback_ctrl(ssl->rbio, cmd, fp);
+ break;
+ }
+ return (ret);
+}
static int ssl_puts(BIO *bp, const char *str)
- {
- int n,ret;
+{
+ int n, ret;
- n=strlen(str);
- ret=BIO_write(bp,str,n);
- return(ret);
- }
+ n = strlen(str);
+ ret = BIO_write(bp, str, n);
+ return (ret);
+}
BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx)
- {
+{
#ifndef OPENSSL_NO_SOCK
- BIO *ret=NULL,*buf=NULL,*ssl=NULL;
-
- if ((buf=BIO_new(BIO_f_buffer())) == NULL)
- return(NULL);
- if ((ssl=BIO_new_ssl_connect(ctx)) == NULL)
- goto err;
- if ((ret=BIO_push(buf,ssl)) == NULL)
- goto err;
- return(ret);
-err:
- if (buf != NULL) BIO_free(buf);
- if (ssl != NULL) BIO_free(ssl);
+ BIO *ret = NULL, *buf = NULL, *ssl = NULL;
+
+ if ((buf = BIO_new(BIO_f_buffer())) == NULL)
+ return (NULL);
+ if ((ssl = BIO_new_ssl_connect(ctx)) == NULL)
+ goto err;
+ if ((ret = BIO_push(buf, ssl)) == NULL)
+ goto err;
+ return (ret);
+ err:
+ if (buf != NULL)
+ BIO_free(buf);
+ if (ssl != NULL)
+ BIO_free(ssl);
#endif
- return(NULL);
- }
+ return (NULL);
+}
BIO *BIO_new_ssl_connect(SSL_CTX *ctx)
- {
+{
#ifndef OPENSSL_NO_SOCK
- BIO *ret=NULL,*con=NULL,*ssl=NULL;
-
- if ((con=BIO_new(BIO_s_connect())) == NULL)
- return(NULL);
- if ((ssl=BIO_new_ssl(ctx,1)) == NULL)
- goto err;
- if ((ret=BIO_push(ssl,con)) == NULL)
- goto err;
- return(ret);
-err:
- if (con != NULL) BIO_free(con);
+ BIO *ret = NULL, *con = NULL, *ssl = NULL;
+
+ if ((con = BIO_new(BIO_s_connect())) == NULL)
+ return (NULL);
+ if ((ssl = BIO_new_ssl(ctx, 1)) == NULL)
+ goto err;
+ if ((ret = BIO_push(ssl, con)) == NULL)
+ goto err;
+ return (ret);
+ err:
+ if (con != NULL)
+ BIO_free(con);
#endif
- return(NULL);
- }
+ return (NULL);
+}
BIO *BIO_new_ssl(SSL_CTX *ctx, int client)
- {
- BIO *ret;
- SSL *ssl;
-
- if ((ret=BIO_new(BIO_f_ssl())) == NULL)
- return(NULL);
- if ((ssl=SSL_new(ctx)) == NULL)
- {
- BIO_free(ret);
- return(NULL);
- }
- if (client)
- SSL_set_connect_state(ssl);
- else
- SSL_set_accept_state(ssl);
-
- BIO_set_ssl(ret,ssl,BIO_CLOSE);
- return(ret);
- }
+{
+ BIO *ret;
+ SSL *ssl;
+
+ if ((ret = BIO_new(BIO_f_ssl())) == NULL)
+ return (NULL);
+ if ((ssl = SSL_new(ctx)) == NULL) {
+ BIO_free(ret);
+ return (NULL);
+ }
+ if (client)
+ SSL_set_connect_state(ssl);
+ else
+ SSL_set_accept_state(ssl);
+
+ BIO_set_ssl(ret, ssl, BIO_CLOSE);
+ return (ret);
+}
int BIO_ssl_copy_session_id(BIO *t, BIO *f)
- {
- t=BIO_find_type(t,BIO_TYPE_SSL);
- f=BIO_find_type(f,BIO_TYPE_SSL);
- if ((t == NULL) || (f == NULL))
- return(0);
- if ( (((BIO_SSL *)t->ptr)->ssl == NULL) ||
- (((BIO_SSL *)f->ptr)->ssl == NULL))
- return(0);
- SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl);
- return(1);
- }
+{
+ t = BIO_find_type(t, BIO_TYPE_SSL);
+ f = BIO_find_type(f, BIO_TYPE_SSL);
+ if ((t == NULL) || (f == NULL))
+ return (0);
+ if ((((BIO_SSL *)t->ptr)->ssl == NULL) ||
+ (((BIO_SSL *)f->ptr)->ssl == NULL))
+ return (0);
+ SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl, ((BIO_SSL *)f->ptr)->ssl);
+ return (1);
+}
void BIO_ssl_shutdown(BIO *b)
- {
- SSL *s;
-
- while (b != NULL)
- {
- if (b->method->type == BIO_TYPE_SSL)
- {
- s=((BIO_SSL *)b->ptr)->ssl;
- SSL_shutdown(s);
- break;
- }
- b=b->next_bio;
- }
- }
+{
+ SSL *s;
+
+ while (b != NULL) {
+ if (b->method->type == BIO_TYPE_SSL) {
+ s = ((BIO_SSL *)b->ptr)->ssl;
+ SSL_shutdown(s);
+ break;
+ }
+ b = b->next_bio;
+ }
+}
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 1b9d64bf6027..c18ec03bd14b 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -1,7 +1,7 @@
/* ssl/d1_both.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,21 +62,21 @@
* 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:
@@ -91,10 +91,10 @@
* 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
+ * 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
@@ -106,7 +106,7 @@
* 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
@@ -126,1537 +126,1520 @@
#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
- if ((end) - (start) <= 8) { \
- long ii; \
- for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
- } else { \
- long ii; \
- bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
- for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
- bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
- } }
+ if ((end) - (start) <= 8) { \
+ long ii; \
+ for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
+ } else { \
+ long ii; \
+ bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
+ for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
+ bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
+ } }
#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
- long ii; \
- OPENSSL_assert((msg_len) > 0); \
- is_complete = 1; \
- if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
- if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
- if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
+ long ii; \
+ OPENSSL_assert((msg_len) > 0); \
+ is_complete = 1; \
+ if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
+ if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
+ if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
#if 0
-#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
- long ii; \
- printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
- printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
- printf("\n"); }
+# define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \
+ long ii; \
+ printf("bitmask: "); for (ii = 0; ii < (msg_len); ii++) \
+ printf("%d ", (bitmask[ii >> 3] & (1 << (ii & 7))) >> (ii & 7)); \
+ printf("\n"); }
#endif
-static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
-static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
+static unsigned char bitmask_start_values[] =
+ { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
+static unsigned char bitmask_end_values[] =
+ { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
/* XDTLS: figure out the right values */
-static const unsigned int g_probable_mtu[] = {1500, 512, 256};
+static const unsigned int g_probable_mtu[] = { 1500, 512, 256 };
-static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
- unsigned long frag_len);
-static unsigned char *dtls1_write_message_header(SSL *s,
- unsigned char *p);
+static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
+ unsigned long frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
- unsigned long len, unsigned short seq_num, unsigned long frag_off,
- unsigned long frag_len);
-static long dtls1_get_message_fragment(SSL *s, int st1, int stn,
- long max, int *ok);
-
-static hm_fragment *
-dtls1_hm_fragment_new(unsigned long frag_len, int reassembly)
- {
- hm_fragment *frag = NULL;
- unsigned char *buf = NULL;
- unsigned char *bitmask = NULL;
-
- frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
- if ( frag == NULL)
- return NULL;
-
- if (frag_len)
- {
- buf = (unsigned char *)OPENSSL_malloc(frag_len);
- if ( buf == NULL)
- {
- OPENSSL_free(frag);
- return NULL;
- }
- }
-
- /* zero length fragment gets zero frag->fragment */
- frag->fragment = buf;
-
- /* Initialize reassembly bitmask if necessary */
- if (reassembly)
- {
- bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
- if (bitmask == NULL)
- {
- if (buf != NULL) OPENSSL_free(buf);
- OPENSSL_free(frag);
- return NULL;
- }
- memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
- }
-
- frag->reassembly = bitmask;
-
- return frag;
- }
+ unsigned long len,
+ unsigned short seq_num,
+ unsigned long frag_off,
+ unsigned long frag_len);
+static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max,
+ int *ok);
+
+static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
+ int reassembly)
+{
+ hm_fragment *frag = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *bitmask = NULL;
+
+ frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
+ if (frag == NULL)
+ return NULL;
+
+ if (frag_len) {
+ buf = (unsigned char *)OPENSSL_malloc(frag_len);
+ if (buf == NULL) {
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ /* zero length fragment gets zero frag->fragment */
+ frag->fragment = buf;
+
+ /* Initialize reassembly bitmask if necessary */
+ if (reassembly) {
+ bitmask =
+ (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len));
+ if (bitmask == NULL) {
+ if (buf != NULL)
+ OPENSSL_free(buf);
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len));
+ }
+
+ frag->reassembly = bitmask;
+
+ return frag;
+}
void dtls1_hm_fragment_free(hm_fragment *frag)
- {
-
- if (frag->msg_header.is_ccs)
- {
- EVP_CIPHER_CTX_free(frag->msg_header.saved_retransmit_state.enc_write_ctx);
- EVP_MD_CTX_destroy(frag->msg_header.saved_retransmit_state.write_hash);
- }
- if (frag->fragment) OPENSSL_free(frag->fragment);
- if (frag->reassembly) OPENSSL_free(frag->reassembly);
- OPENSSL_free(frag);
- }
+{
+
+ if (frag->msg_header.is_ccs) {
+ EVP_CIPHER_CTX_free(frag->msg_header.
+ saved_retransmit_state.enc_write_ctx);
+ EVP_MD_CTX_destroy(frag->msg_header.
+ saved_retransmit_state.write_hash);
+ }
+ if (frag->fragment)
+ OPENSSL_free(frag->fragment);
+ if (frag->reassembly)
+ OPENSSL_free(frag->reassembly);
+ OPENSSL_free(frag);
+}
static int dtls1_query_mtu(SSL *s)
{
- if(s->d1->link_mtu)
- {
- s->d1->mtu = s->d1->link_mtu-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
- s->d1->link_mtu = 0;
- }
-
- /* AHA! Figure out the MTU, and stick to the right size */
- if (s->d1->mtu < dtls1_min_mtu(s))
- {
- if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
- {
- s->d1->mtu =
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
-
- /* I've seen the kernel return bogus numbers when it doesn't know
- * (initial write), so just make sure we have a reasonable number */
- if (s->d1->mtu < dtls1_min_mtu(s))
- {
- /* Set to min mtu */
- s->d1->mtu = dtls1_min_mtu(s);
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
- s->d1->mtu, NULL);
- }
- }
- else
- return 0;
- }
- return 1;
+ if (s->d1->link_mtu) {
+ s->d1->mtu =
+ s->d1->link_mtu - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+ s->d1->link_mtu = 0;
+ }
+
+ /* AHA! Figure out the MTU, and stick to the right size */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ s->d1->mtu =
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+
+ /*
+ * I've seen the kernel return bogus numbers when it doesn't know
+ * (initial write), so just make sure we have a reasonable number
+ */
+ if (s->d1->mtu < dtls1_min_mtu(s)) {
+ /* Set to min mtu */
+ s->d1->mtu = dtls1_min_mtu(s);
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU,
+ s->d1->mtu, NULL);
+ }
+ } else
+ return 0;
+ }
+ return 1;
}
-/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
int dtls1_do_write(SSL *s, int type)
- {
- int ret;
- unsigned int curr_mtu;
- int retry = 1;
- unsigned int len, frag_off, mac_size, blocksize, used_len;
-
- if(!dtls1_query_mtu(s))
- return -1;
-
- OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something reasonable now */
-
- if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
- OPENSSL_assert(s->init_num ==
- (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
- mac_size = 0;
-
- if (s->enc_write_ctx &&
- (EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE))
- blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
- else
- blocksize = 0;
-
- frag_off = 0;
- /* s->init_num shouldn't ever be < 0...but just in case */
- while(s->init_num > 0)
- {
- used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
- + mac_size + blocksize;
- if(s->d1->mtu > used_len)
- curr_mtu = s->d1->mtu - used_len;
- else
- curr_mtu = 0;
-
- if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
- {
- /* grr.. we could get an error if MTU picked was wrong */
- ret = BIO_flush(SSL_get_wbio(s));
- if ( ret <= 0)
- return ret;
- used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
- if(s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH)
- {
- curr_mtu = s->d1->mtu - used_len;
- }
- else
- {
- /* Shouldn't happen */
- return -1;
- }
- }
-
- /* We just checked that s->init_num > 0 so this cast should be safe */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
-
- /* Shouldn't ever happen */
- if(len > INT_MAX)
- len = INT_MAX;
-
- /* XDTLS: this function is too long. split out the CCS part */
- if ( type == SSL3_RT_HANDSHAKE)
- {
- if ( s->init_off != 0)
- {
- OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
- s->init_off -= DTLS1_HM_HEADER_LENGTH;
- s->init_num += DTLS1_HM_HEADER_LENGTH;
-
- /* We just checked that s->init_num > 0 so this cast should be safe */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
- }
-
- /* Shouldn't ever happen */
- if(len > INT_MAX)
- len = INT_MAX;
-
- if ( len < DTLS1_HM_HEADER_LENGTH )
- {
- /*
- * len is so small that we really can't do anything sensible
- * so fail
- */
- return -1;
- }
- dtls1_fix_message_header(s, frag_off,
- len - DTLS1_HM_HEADER_LENGTH);
-
- dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);
- }
-
- ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
- len);
- if (ret < 0)
- {
- /* might need to update MTU here, but we don't know
- * which previous packet caused the failure -- so can't
- * really retransmit anything. continue as if everything
- * is fine and wait for an alert to handle the
- * retransmit
- */
- if ( retry && BIO_ctrl(SSL_get_wbio(s),
- BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0 )
- {
- if(!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
- {
- if(!dtls1_query_mtu(s))
- return -1;
- /* Have one more go */
- retry = 0;
- }
- else
- return -1;
- }
- else
- {
- return(-1);
- }
- }
- else
- {
-
- /* bad if this assert fails, only part of the handshake
- * message got sent. but why would this happen? */
- OPENSSL_assert(len == (unsigned int)ret);
-
- if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
- {
- /* should not be done for 'Hello Request's, but in that case
- * we'll ignore the result anyway */
- unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
- const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
- int xlen;
-
- if (frag_off == 0 && s->version != DTLS1_BAD_VER)
- {
- /* reconstruct message header is if it
- * is being sent in single fragment */
- *p++ = msg_hdr->type;
- l2n3(msg_hdr->msg_len,p);
- s2n (msg_hdr->seq,p);
- l2n3(0,p);
- l2n3(msg_hdr->msg_len,p);
- p -= DTLS1_HM_HEADER_LENGTH;
- xlen = ret;
- }
- else
- {
- p += DTLS1_HM_HEADER_LENGTH;
- xlen = ret - DTLS1_HM_HEADER_LENGTH;
- }
-
- ssl3_finish_mac(s, p, xlen);
- }
-
- if (ret == s->init_num)
- {
- if (s->msg_callback)
- s->msg_callback(1, s->version, type, s->init_buf->data,
- (size_t)(s->init_off + s->init_num), s,
- s->msg_callback_arg);
-
- s->init_off = 0; /* done writing this message */
- s->init_num = 0;
-
- return(1);
- }
- s->init_off+=ret;
- s->init_num-=ret;
- frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
- }
- }
- return(0);
- }
-
-
-/* Obtain handshake message of message type 'mt' (any if mt == -1),
- * maximum acceptable body length 'max'.
- * Read an entire handshake message. Handshake messages arrive in
- * fragments.
+{
+ int ret;
+ unsigned int curr_mtu;
+ int retry = 1;
+ unsigned int len, frag_off, mac_size, blocksize, used_len;
+
+ if (!dtls1_query_mtu(s))
+ return -1;
+
+ OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu(s)); /* should have something
+ * reasonable now */
+
+ if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
+ OPENSSL_assert(s->init_num ==
+ (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
+ mac_size = 0;
+
+ if (s->enc_write_ctx &&
+ (EVP_CIPHER_mode(s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE))
+ blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher);
+ else
+ blocksize = 0;
+
+ frag_off = 0;
+ /* s->init_num shouldn't ever be < 0...but just in case */
+ while (s->init_num > 0) {
+ used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
+ + mac_size + blocksize;
+ if (s->d1->mtu > used_len)
+ curr_mtu = s->d1->mtu - used_len;
+ else
+ curr_mtu = 0;
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * grr.. we could get an error if MTU picked was wrong
+ */
+ ret = BIO_flush(SSL_get_wbio(s));
+ if (ret <= 0)
+ return ret;
+ used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
+ if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
+ curr_mtu = s->d1->mtu - used_len;
+ } else {
+ /* Shouldn't happen */
+ return -1;
+ }
+ }
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+
+ /* Shouldn't ever happen */
+ if (len > INT_MAX)
+ len = INT_MAX;
+
+ /*
+ * XDTLS: this function is too long. split out the CCS part
+ */
+ if (type == SSL3_RT_HANDSHAKE) {
+ if (s->init_off != 0) {
+ OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should
+ * be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+ }
+
+ /* Shouldn't ever happen */
+ if (len > INT_MAX)
+ len = INT_MAX;
+
+ if (len < DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * len is so small that we really can't do anything sensible
+ * so fail
+ */
+ return -1;
+ }
+ dtls1_fix_message_header(s, frag_off,
+ len - DTLS1_HM_HEADER_LENGTH);
+
+ dtls1_write_message_header(s,
+ (unsigned char *)&s->init_buf->
+ data[s->init_off]);
+ }
+
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off],
+ len);
+ if (ret < 0) {
+ /*
+ * might need to update MTU here, but we don't know which
+ * previous packet caused the failure -- so can't really
+ * retransmit anything. continue as if everything is fine and
+ * wait for an alert to handle the retransmit
+ */
+ if (retry && BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ if (!dtls1_query_mtu(s))
+ return -1;
+ /* Have one more go */
+ retry = 0;
+ } else
+ return -1;
+ } else {
+ return (-1);
+ }
+ } else {
+
+ /*
+ * bad if this assert fails, only part of the handshake message
+ * got sent. but why would this happen?
+ */
+ OPENSSL_assert(len == (unsigned int)ret);
+
+ if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
+ /*
+ * should not be done for 'Hello Request's, but in that case
+ * we'll ignore the result anyway
+ */
+ unsigned char *p =
+ (unsigned char *)&s->init_buf->data[s->init_off];
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ int xlen;
+
+ if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
+ /*
+ * reconstruct message header is if it is being sent in
+ * single fragment
+ */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ p -= DTLS1_HM_HEADER_LENGTH;
+ xlen = ret;
+ } else {
+ p += DTLS1_HM_HEADER_LENGTH;
+ xlen = ret - DTLS1_HM_HEADER_LENGTH;
+ }
+
+ ssl3_finish_mac(s, p, xlen);
+ }
+
+ if (ret == s->init_num) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, type, s->init_buf->data,
+ (size_t)(s->init_off + s->init_num), s,
+ s->msg_callback_arg);
+
+ s->init_off = 0; /* done writing this message */
+ s->init_num = 0;
+
+ return (1);
+ }
+ s->init_off += ret;
+ s->init_num -= ret;
+ frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Obtain handshake message of message type 'mt' (any if mt == -1), maximum
+ * acceptable body length 'max'. Read an entire handshake message. Handshake
+ * messages arrive in fragments.
*/
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
- {
- int i, al;
- struct hm_header_st *msg_hdr;
- unsigned char *p;
- unsigned long msg_len;
-
- /* s3->tmp is used to store messages that are unexpected, caused
- * by the absence of an optional handshake message */
- if (s->s3->tmp.reuse_message)
- {
- s->s3->tmp.reuse_message=0;
- if ((mt >= 0) && (s->s3->tmp.message_type != mt))
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
- *ok=1;
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- s->init_num = (int)s->s3->tmp.message_size;
- return s->init_num;
- }
-
- msg_hdr = &s->d1->r_msg_hdr;
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-
-again:
- i = dtls1_get_message_fragment(s, st1, stn, max, ok);
- if ( i == DTLS1_HM_BAD_FRAGMENT ||
- i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */
- goto again;
- else if ( i <= 0 && !*ok)
- return i;
-
- p = (unsigned char *)s->init_buf->data;
- msg_len = msg_hdr->msg_len;
-
- /* reconstruct message header */
- *(p++) = msg_hdr->type;
- l2n3(msg_len,p);
- s2n (msg_hdr->seq,p);
- l2n3(0,p);
- l2n3(msg_len,p);
- if (s->version != DTLS1_BAD_VER) {
- p -= DTLS1_HM_HEADER_LENGTH;
- msg_len += DTLS1_HM_HEADER_LENGTH;
- }
-
- ssl3_finish_mac(s, p, msg_len);
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, msg_len,
- s, s->msg_callback_arg);
-
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-
- /* Don't change sequence numbers while listening */
- if (!s->d1->listen)
- s->d1->handshake_read_seq++;
-
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- return s->init_num;
-
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- *ok = 0;
- return -1;
- }
-
-
-static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
- {
- size_t frag_off,frag_len,msg_len;
-
- msg_len = msg_hdr->msg_len;
- frag_off = msg_hdr->frag_off;
- frag_len = msg_hdr->frag_len;
-
- /* sanity checking */
- if ( (frag_off+frag_len) > msg_len)
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- if ( (frag_off+frag_len) > (unsigned long)max)
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
- {
- /* msg_len is limited to 2^24, but is effectively checked
- * against max above */
- if (!BUF_MEM_grow_clean(s->init_buf,msg_len+DTLS1_HM_HEADER_LENGTH))
- {
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
- return SSL_AD_INTERNAL_ERROR;
- }
-
- s->s3->tmp.message_size = msg_len;
- s->d1->r_msg_hdr.msg_len = msg_len;
- s->s3->tmp.message_type = msg_hdr->type;
- s->d1->r_msg_hdr.type = msg_hdr->type;
- s->d1->r_msg_hdr.seq = msg_hdr->seq;
- }
- else if (msg_len != s->d1->r_msg_hdr.msg_len)
- {
- /* They must be playing with us! BTW, failure to enforce
- * upper limit would open possibility for buffer overrun. */
- SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SSL_AD_ILLEGAL_PARAMETER;
- }
-
- return 0; /* no error */
- }
+{
+ int i, al;
+ struct hm_header_st *msg_hdr;
+ unsigned char *p;
+ unsigned long msg_len;
+
+ /*
+ * s3->tmp is used to store messages that are unexpected, caused by the
+ * absence of an optional handshake message
+ */
+ if (s->s3->tmp.reuse_message) {
+ s->s3->tmp.reuse_message = 0;
+ if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ *ok = 1;
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ s->init_num = (int)s->s3->tmp.message_size;
+ return s->init_num;
+ }
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+ again:
+ i = dtls1_get_message_fragment(s, st1, stn, max, ok);
+ if (i == DTLS1_HM_BAD_FRAGMENT || i == DTLS1_HM_FRAGMENT_RETRY) {
+ /* bad fragment received */
+ goto again;
+ } else if (i <= 0 && !*ok) {
+ return i;
+ }
+
+ p = (unsigned char *)s->init_buf->data;
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ ssl3_finish_mac(s, p, msg_len);
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, msg_len, s, s->msg_callback_arg);
+
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+
+ /* Don't change sequence numbers while listening */
+ if (!s->d1->listen)
+ s->d1->handshake_read_seq++;
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ return s->init_num;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ *ok = 0;
+ return -1;
+}
+static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr,
+ int max)
+{
+ size_t frag_off, frag_len, msg_len;
+
+ msg_len = msg_hdr->msg_len;
+ frag_off = msg_hdr->frag_off;
+ frag_len = msg_hdr->frag_len;
+
+ /* sanity checking */
+ if ((frag_off + frag_len) > msg_len) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if ((frag_off + frag_len) > (unsigned long)max) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
+ /*
+ * msg_len is limited to 2^24, but is effectively checked against max
+ * above
+ */
+ if (!BUF_MEM_grow_clean
+ (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
+ return SSL_AD_INTERNAL_ERROR;
+ }
+
+ s->s3->tmp.message_size = msg_len;
+ s->d1->r_msg_hdr.msg_len = msg_len;
+ s->s3->tmp.message_type = msg_hdr->type;
+ s->d1->r_msg_hdr.type = msg_hdr->type;
+ s->d1->r_msg_hdr.seq = msg_hdr->seq;
+ } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
+ /*
+ * They must be playing with us! BTW, failure to enforce upper limit
+ * would open possibility for buffer overrun.
+ */
+ SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SSL_AD_ILLEGAL_PARAMETER;
+ }
+
+ return 0; /* no error */
+}
-static int
-dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
- {
- /* (0) check whether the desired fragment is available
- * if so:
- * (1) copy over the fragment to s->init_buf->data[]
- * (2) update s->init_num
- */
- pitem *item;
- hm_fragment *frag;
- int al;
-
- *ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if ( item == NULL)
- return 0;
-
- frag = (hm_fragment *)item->data;
-
- /* Don't return if reassembly still in progress */
- if (frag->reassembly != NULL)
- return 0;
-
- if ( s->d1->handshake_read_seq == frag->msg_header.seq)
- {
- unsigned long frag_len = frag->msg_header.frag_len;
- pqueue_pop(s->d1->buffered_messages);
-
- al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
-
- if (al==0) /* no alert */
- {
- unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
- memcpy(&p[frag->msg_header.frag_off],
- frag->fragment,frag->msg_header.frag_len);
- }
-
- dtls1_hm_fragment_free(frag);
- pitem_free(item);
-
- if (al==0)
- {
- *ok = 1;
- return frag_len;
- }
-
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- s->init_num = 0;
- *ok = 0;
- return -1;
- }
- else
- return 0;
- }
-
-/* dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
- * be greater if the maximum certificate list size requires it. */
+static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
+{
+ /*-
+ * (0) check whether the desired fragment is available
+ * if so:
+ * (1) copy over the fragment to s->init_buf->data[]
+ * (2) update s->init_num
+ */
+ pitem *item;
+ hm_fragment *frag;
+ int al;
+
+ *ok = 0;
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ /* Don't return if reassembly still in progress */
+ if (frag->reassembly != NULL)
+ return 0;
+
+ if (s->d1->handshake_read_seq == frag->msg_header.seq) {
+ unsigned long frag_len = frag->msg_header.frag_len;
+ pqueue_pop(s->d1->buffered_messages);
+
+ al = dtls1_preprocess_fragment(s, &frag->msg_header, max);
+
+ if (al == 0) { /* no alert */
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ memcpy(&p[frag->msg_header.frag_off], frag->fragment,
+ frag->msg_header.frag_len);
+ }
+
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+
+ if (al == 0) {
+ *ok = 1;
+ return frag_len;
+ }
+
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->init_num = 0;
+ *ok = 0;
+ return -1;
+ } else
+ return 0;
+}
+
+/*
+ * dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
+ * may be greater if the maximum certificate list size requires it.
+ */
static unsigned long dtls1_max_handshake_message_len(const SSL *s)
- {
- unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
- if (max_len < (unsigned long)s->max_cert_list)
- return s->max_cert_list;
- return max_len;
- }
+{
+ unsigned long max_len =
+ DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < (unsigned long)s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+}
static int
-dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
- {
- hm_fragment *frag = NULL;
- pitem *item = NULL;
- int i = -1, is_complete;
- unsigned char seq64be[8];
- unsigned long frag_len = msg_hdr->frag_len;
-
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
- msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
- goto err;
-
- if (frag_len == 0)
- return DTLS1_HM_FRAGMENT_RETRY;
-
- /* Try to find item in queue */
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
- seq64be[7] = (unsigned char) msg_hdr->seq;
- item = pqueue_find(s->d1->buffered_messages, seq64be);
-
- if (item == NULL)
- {
- frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
- if ( frag == NULL)
- goto err;
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
- frag->msg_header.frag_len = frag->msg_header.msg_len;
- frag->msg_header.frag_off = 0;
- }
- else
- {
- frag = (hm_fragment*) item->data;
- if (frag->msg_header.msg_len != msg_hdr->msg_len)
- {
- item = NULL;
- frag = NULL;
- goto err;
- }
- }
-
-
- /* If message is already reassembled, this must be a
- * retransmit and can be dropped. In this case item != NULL and so frag
- * does not need to be freed.
- */
- if (frag->reassembly == NULL)
- {
- unsigned char devnull [256];
-
- while (frag_len)
- {
- i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
- devnull,
- frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
- if (i<=0) goto err;
- frag_len -= i;
- }
- return DTLS1_HM_FRAGMENT_RETRY;
- }
-
- /* read the body of the fragment (header has already been read */
- i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
- frag->fragment + msg_hdr->frag_off,frag_len,0);
- if ((unsigned long)i!=frag_len)
- i=-1;
- if (i<=0)
- goto err;
-
- RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
- (long)(msg_hdr->frag_off + frag_len));
-
- RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
- is_complete);
-
- if (is_complete)
- {
- OPENSSL_free(frag->reassembly);
- frag->reassembly = NULL;
- }
-
- if (item == NULL)
- {
- item = pitem_new(seq64be, frag);
- if (item == NULL)
- {
- i = -1;
- goto err;
- }
-
- item = pqueue_insert(s->d1->buffered_messages, item);
- /* pqueue_insert fails iff a duplicate item is inserted.
- * However, |item| cannot be a duplicate. If it were,
- * |pqueue_find|, above, would have returned it and control
- * would never have reached this branch. */
- OPENSSL_assert(item != NULL);
- }
-
- return DTLS1_HM_FRAGMENT_RETRY;
-
-err:
- if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
- *ok = 0;
- return i;
- }
-
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
+{
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ int i = -1, is_complete;
+ unsigned char seq64be[8];
+ unsigned long frag_len = msg_hdr->frag_len;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ if (frag_len == 0)
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ /* Try to find item in queue */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ if (item == NULL) {
+ frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
+ if (frag == NULL)
+ goto err;
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+ frag->msg_header.frag_len = frag->msg_header.msg_len;
+ frag->msg_header.frag_off = 0;
+ } else {
+ frag = (hm_fragment *)item->data;
+ if (frag->msg_header.msg_len != msg_hdr->msg_len) {
+ item = NULL;
+ frag = NULL;
+ goto err;
+ }
+ }
+
+ /*
+ * If message is already reassembled, this must be a retransmit and can
+ * be dropped. In this case item != NULL and so frag does not need to be
+ * freed.
+ */
+ if (frag->reassembly == NULL) {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0);
+ if (i <= 0)
+ goto err;
+ frag_len -= i;
+ }
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* read the body of the fragment (header has already been read */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
+ frag->fragment + msg_hdr->frag_off,
+ frag_len, 0);
+ if ((unsigned long)i != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+
+ RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
+ (long)(msg_hdr->frag_off + frag_len));
+
+ RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
+ is_complete);
+
+ if (is_complete) {
+ OPENSSL_free(frag->reassembly);
+ frag->reassembly = NULL;
+ }
+
+ if (item == NULL) {
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ i = -1;
+ goto err;
+ }
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it and control would never have reached this
+ * branch.
+ */
+ OPENSSL_assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (frag != NULL && item == NULL)
+ dtls1_hm_fragment_free(frag);
+ *ok = 0;
+ return i;
+}
static int
-dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
+ int *ok)
{
- int i=-1;
- hm_fragment *frag = NULL;
- pitem *item = NULL;
- unsigned char seq64be[8];
- unsigned long frag_len = msg_hdr->frag_len;
-
- if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
- goto err;
-
- /* Try to find item in queue, to prevent duplicate entries */
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
- seq64be[7] = (unsigned char) msg_hdr->seq;
- item = pqueue_find(s->d1->buffered_messages, seq64be);
-
- /* If we already have an entry and this one is a fragment,
- * don't discard it and rather try to reassemble it.
- */
- if (item != NULL && frag_len != msg_hdr->msg_len)
- item = NULL;
-
- /* Discard the message if sequence number was already there, is
- * too far in the future, already in the queue or if we received
- * a FINISHED before the SERVER_HELLO, which then must be a stale
- * retransmit.
- */
- if (msg_hdr->seq <= s->d1->handshake_read_seq ||
- msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
- (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
- {
- unsigned char devnull [256];
-
- while (frag_len)
- {
- i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
- devnull,
- frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
- if (i<=0) goto err;
- frag_len -= i;
- }
- }
- else
- {
- if (frag_len != msg_hdr->msg_len)
- return dtls1_reassemble_fragment(s, msg_hdr, ok);
-
- if (frag_len > dtls1_max_handshake_message_len(s))
- goto err;
-
- frag = dtls1_hm_fragment_new(frag_len, 0);
- if ( frag == NULL)
- goto err;
-
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
-
- if (frag_len)
- {
- /* read the body of the fragment (header has already been read */
- i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
- frag->fragment,frag_len,0);
- if ((unsigned long)i!=frag_len)
- i = -1;
- if (i<=0)
- goto err;
- }
-
- item = pitem_new(seq64be, frag);
- if ( item == NULL)
- goto err;
-
- item = pqueue_insert(s->d1->buffered_messages, item);
- /* pqueue_insert fails iff a duplicate item is inserted.
- * However, |item| cannot be a duplicate. If it were,
- * |pqueue_find|, above, would have returned it. Then, either
- * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
- * to NULL and it will have been processed with
- * |dtls1_reassemble_fragment|, above, or the record will have
- * been discarded. */
- OPENSSL_assert(item != NULL);
- }
-
- return DTLS1_HM_FRAGMENT_RETRY;
-
-err:
- if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
- *ok = 0;
- return i;
- }
-
+ int i = -1;
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ unsigned char seq64be[8];
+ unsigned long frag_len = msg_hdr->frag_len;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
+ goto err;
+
+ /* Try to find item in queue, to prevent duplicate entries */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ /*
+ * If we already have an entry and this one is a fragment, don't discard
+ * it and rather try to reassemble it.
+ */
+ if (item != NULL && frag_len != msg_hdr->msg_len)
+ item = NULL;
+
+ /*
+ * Discard the message if sequence number was already there, is too far
+ * in the future, already in the queue or if we received a FINISHED
+ * before the SERVER_HELLO, which then must be a stale retransmit.
+ */
+ if (msg_hdr->seq <= s->d1->handshake_read_seq ||
+ msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
+ (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED))
+ {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0);
+ if (i <= 0)
+ goto err;
+ frag_len -= i;
+ }
+ } else {
+ if (frag_len != msg_hdr->msg_len)
+ return dtls1_reassemble_fragment(s, msg_hdr, ok);
+
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ frag = dtls1_hm_fragment_new(frag_len, 0);
+ if (frag == NULL)
+ goto err;
+
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
+ if (frag_len) {
+ /*
+ * read the body of the fragment (header has already been read
+ */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
+ frag->fragment, frag_len, 0);
+ if ((unsigned long)i != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+ }
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL)
+ goto err;
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it. Then, either |frag_len| !=
+ * |msg_hdr->msg_len| in which case |item| is set to NULL and it will
+ * have been processed with |dtls1_reassemble_fragment|, above, or
+ * the record will have been discarded.
+ */
+ OPENSSL_assert(item != NULL);
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (frag != NULL && item == NULL)
+ dtls1_hm_fragment_free(frag);
+ *ok = 0;
+ return i;
+}
static long
dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
- {
- unsigned char wire[DTLS1_HM_HEADER_LENGTH];
- unsigned long len, frag_off, frag_len;
- int i,al;
- struct hm_header_st msg_hdr;
-
- redo:
- /* see if we have the required fragment already */
- if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
- {
- if (*ok) s->init_num = frag_len;
- return frag_len;
- }
-
- /* read handshake message header */
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
- DTLS1_HM_HEADER_LENGTH, 0);
- if (i <= 0) /* nbio, or an error */
- {
- s->rwstate=SSL_READING;
- *ok = 0;
- return i;
- }
- /* Handshake fails if message header is incomplete */
- if (i != DTLS1_HM_HEADER_LENGTH)
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
-
- /* parse the message fragment header */
- dtls1_get_message_header(wire, &msg_hdr);
-
- /*
- * if this is a future (or stale) message it gets buffered
- * (or dropped)--no further processing at this time
- * While listening, we accept seq 1 (ClientHello with cookie)
- * although we're still expecting seq 0 (ClientHello)
- */
- if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1))
- return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
-
- len = msg_hdr.msg_len;
- frag_off = msg_hdr.frag_off;
- frag_len = msg_hdr.frag_len;
-
- if (frag_len && frag_len < len)
- return dtls1_reassemble_fragment(s, &msg_hdr, ok);
-
- if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
- wire[0] == SSL3_MT_HELLO_REQUEST)
- {
- /* The server may always send 'Hello Request' messages --
- * we are doing a handshake anyway now, so ignore them
- * if their format is correct. Does not count for
- * 'Finished' MAC. */
- if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
- {
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- wire, DTLS1_HM_HEADER_LENGTH, s,
- s->msg_callback_arg);
-
- s->init_num = 0;
- goto redo;
- }
- else /* Incorrectly formated Hello request */
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
- }
-
- if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
- goto f_err;
-
- /* XDTLS: ressurect this when restart is in place */
- s->state=stn;
-
- if ( frag_len > 0)
- {
- unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
-
- i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
- &p[frag_off],frag_len,0);
- /* XDTLS: fix this--message fragments cannot span multiple packets */
- if (i <= 0)
- {
- s->rwstate=SSL_READING;
- *ok = 0;
- return i;
- }
- }
- else
- i = 0;
-
- /* XDTLS: an incorrectly formatted fragment should cause the
- * handshake to fail */
- if (i != (int)frag_len)
- {
- al=SSL3_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER);
- goto f_err;
- }
-
- *ok = 1;
-
- /* Note that s->init_num is *not* used as current offset in
- * s->init_buf->data, but as a counter summing up fragments'
- * lengths: as soon as they sum up to handshake packet
- * length, we assume we have got all the fragments. */
- s->init_num = frag_len;
- return frag_len;
-
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- s->init_num = 0;
-
- *ok=0;
- return(-1);
- }
+{
+ unsigned char wire[DTLS1_HM_HEADER_LENGTH];
+ unsigned long len, frag_off, frag_len;
+ int i, al;
+ struct hm_header_st msg_hdr;
+
+ redo:
+ /* see if we have the required fragment already */
+ if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) {
+ if (*ok)
+ s->init_num = frag_len;
+ return frag_len;
+ }
+
+ /* read handshake message header */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire,
+ DTLS1_HM_HEADER_LENGTH, 0);
+ if (i <= 0) { /* nbio, or an error */
+ s->rwstate = SSL_READING;
+ *ok = 0;
+ return i;
+ }
+ /* Handshake fails if message header is incomplete */
+ if (i != DTLS1_HM_HEADER_LENGTH) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* parse the message fragment header */
+ dtls1_get_message_header(wire, &msg_hdr);
+
+ /*
+ * if this is a future (or stale) message it gets buffered
+ * (or dropped)--no further processing at this time
+ * While listening, we accept seq 1 (ClientHello with cookie)
+ * although we're still expecting seq 0 (ClientHello)
+ */
+ if (msg_hdr.seq != s->d1->handshake_read_seq
+ && !(s->d1->listen && msg_hdr.seq == 1))
+ return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
+
+ len = msg_hdr.msg_len;
+ frag_off = msg_hdr.frag_off;
+ frag_len = msg_hdr.frag_len;
+
+ if (frag_len && frag_len < len)
+ return dtls1_reassemble_fragment(s, &msg_hdr, ok);
+
+ if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
+ wire[0] == SSL3_MT_HELLO_REQUEST) {
+ /*
+ * The server may always send 'Hello Request' messages -- we are
+ * doing a handshake anyway now, so ignore them if their format is
+ * correct. Does not count for 'Finished' MAC.
+ */
+ if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ wire, DTLS1_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+
+ s->init_num = 0;
+ goto redo;
+ } else { /* Incorrectly formated Hello request */
+
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ }
+
+ if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max)))
+ goto f_err;
+
+ /* XDTLS: ressurect this when restart is in place */
+ s->state = stn;
+
+ if (frag_len > 0) {
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
+ &p[frag_off], frag_len, 0);
+ /*
+ * XDTLS: fix this--message fragments cannot span multiple packets
+ */
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ *ok = 0;
+ return i;
+ }
+ } else
+ i = 0;
+
+ /*
+ * XDTLS: an incorrectly formatted fragment should cause the handshake
+ * to fail
+ */
+ if (i != (int)frag_len) {
+ al = SSL3_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL3_AD_ILLEGAL_PARAMETER);
+ goto f_err;
+ }
+
+ *ok = 1;
+
+ /*
+ * Note that s->init_num is *not* used as current offset in
+ * s->init_buf->data, but as a counter summing up fragments' lengths: as
+ * soon as they sum up to handshake packet length, we assume we have got
+ * all the fragments.
+ */
+ s->init_num = frag_len;
+ return frag_len;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->init_num = 0;
+
+ *ok = 0;
+ 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;
- }
+{
+ 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;
+ /*
+ * 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;
+ 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);
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 0);
- s->state=b;
- }
+ s->state = b;
+ }
- /* SSL3_ST_SEND_xxxxxx_HELLO_B */
- return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
- }
+ /* 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
- * ssl->s3->read_sequence zero
- * ssl->s3->read_mac_secret re-init
- * ssl->session->read_sym_enc assign
- * ssl->session->read_compression assign
- * ssl->session->read_hash assign
+/*-
+ * for these 2 messages, we need to
+ * ssl->enc_read_ctx re-init
+ * ssl->s3->read_sequence zero
+ * ssl->s3->read_mac_secret re-init
+ * ssl->session->read_sym_enc assign
+ * ssl->session->read_compression assign
+ * ssl->session->read_hash assign
*/
int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
- {
- unsigned char *p;
+{
+ unsigned char *p;
- if (s->state == a)
- {
- p=(unsigned char *)s->init_buf->data;
- *p++=SSL3_MT_CCS;
- s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
- s->init_num=DTLS1_CCS_HEADER_LENGTH;
+ if (s->state == a) {
+ p = (unsigned char *)s->init_buf->data;
+ *p++ = SSL3_MT_CCS;
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->init_num = DTLS1_CCS_HEADER_LENGTH;
- if (s->version == DTLS1_BAD_VER) {
- s->d1->next_handshake_write_seq++;
- s2n(s->d1->handshake_write_seq,p);
- s->init_num+=2;
- }
+ if (s->version == DTLS1_BAD_VER) {
+ s->d1->next_handshake_write_seq++;
+ s2n(s->d1->handshake_write_seq, p);
+ s->init_num += 2;
+ }
- s->init_off=0;
+ s->init_off = 0;
- dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
- s->d1->handshake_write_seq, 0, 0);
+ dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
+ s->d1->handshake_write_seq, 0, 0);
- /* buffer the message to handle re-xmits */
- dtls1_buffer_message(s, 1);
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 1);
- s->state=b;
- }
+ s->state = b;
+ }
- /* SSL3_ST_CW_CHANGE_B */
- return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
- }
+ /* SSL3_ST_CW_CHANGE_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;
- }
+{
+ 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);
- }
+{
+ 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)
- {
- fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
- return 1;
- }
-
- if (!dtls1_is_timer_expired(s))
- {
- /* not a timeout, none of our business,
- let higher layers handle this. in fact it's probably an error */
- return code;
- }
-
+{
+ if (code > 0) {
+ fprintf(stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
+ return 1;
+ }
+
+ if (!dtls1_is_timer_expired(s)) {
+ /*
+ * not a timeout, none of our business, let higher layers handle
+ * this. in fact it's probably an error
+ */
+ return code;
+ }
#ifndef OPENSSL_NO_HEARTBEATS
- if (!SSL_in_init(s) && !s->tlsext_hb_pending) /* done, no need to send a retransmit */
+ /* done, no need to send a retransmit */
+ if (!SSL_in_init(s) && !s->tlsext_hb_pending)
#else
- if (!SSL_in_init(s)) /* done, no need to send a retransmit */
+ /* done, no need to send a retransmit */
+ if (!SSL_in_init(s))
#endif
- {
- BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
- return code;
- }
-
-#if 0 /* for now, each alert contains only one record number */
- item = pqueue_peek(state->rcvd_records);
- if ( item )
- {
- /* send an alert immediately for all the missing records */
- }
- else
+ {
+ BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
+ return code;
+ }
+#if 0 /* for now, each alert contains only one
+ * record number */
+ item = pqueue_peek(state->rcvd_records);
+ if (item) {
+ /* send an alert immediately for all the missing records */
+ } else
#endif
-#if 0 /* no more alert sending, just retransmit the last set of messages */
- if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
- ssl3_send_alert(s,SSL3_AL_WARNING,
- DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+#if 0 /* no more alert sending, just retransmit the
+ * last set of messages */
+ if (state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
+ ssl3_send_alert(s, SSL3_AL_WARNING,
+ DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
#endif
- return dtls1_handle_timeout(s);
- }
-
-int
-dtls1_get_queue_priority(unsigned short seq, int is_ccs)
- {
- /* The index of the retransmission queue actually is the message sequence number,
- * since the queue only contains messages of a single handshake. However, the
- * ChangeCipherSpec has no message sequence number and so using only the sequence
- * will result in the CCS and Finished having the same index. To prevent this,
- * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted.
- * This does not only differ CSS and Finished, it also maintains the order of the
- * index (important for priority queues) and fits in the unsigned short variable.
- */
- return seq * 2 - is_ccs;
- }
+ return dtls1_handle_timeout(s);
+}
-int
-dtls1_retransmit_buffered_messages(SSL *s)
- {
- pqueue sent = s->d1->sent_messages;
- piterator iter;
- pitem *item;
- hm_fragment *frag;
- int found = 0;
-
- iter = pqueue_iterator(sent);
-
- for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
- {
- frag = (hm_fragment *)item->data;
- if ( dtls1_retransmit_message(s,
- (unsigned short)dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs),
- 0, &found) <= 0 && found)
- {
- fprintf(stderr, "dtls1_retransmit_message() failed\n");
- return -1;
- }
- }
-
- return 1;
- }
+int dtls1_get_queue_priority(unsigned short seq, int is_ccs)
+{
+ /*
+ * The index of the retransmission queue actually is the message sequence
+ * number, since the queue only contains messages of a single handshake.
+ * However, the ChangeCipherSpec has no message sequence number and so
+ * using only the sequence will result in the CCS and Finished having the
+ * same index. To prevent this, the sequence number is multiplied by 2.
+ * In case of a CCS 1 is subtracted. This does not only differ CSS and
+ * Finished, it also maintains the order of the index (important for
+ * priority queues) and fits in the unsigned short variable.
+ */
+ return seq * 2 - is_ccs;
+}
-int
-dtls1_buffer_message(SSL *s, int is_ccs)
- {
- pitem *item;
- hm_fragment *frag;
- unsigned char seq64be[8];
-
- /* this function is called immediately after a message has
- * been serialized */
- OPENSSL_assert(s->init_off == 0);
-
- frag = dtls1_hm_fragment_new(s->init_num, 0);
- if (!frag)
- return 0;
-
- memcpy(frag->fragment, s->init_buf->data, s->init_num);
-
- if ( is_ccs)
- {
- OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
- ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num);
- }
- else
- {
- OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
- DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
- }
-
- frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
- frag->msg_header.seq = s->d1->w_msg_hdr.seq;
- frag->msg_header.type = s->d1->w_msg_hdr.type;
- frag->msg_header.frag_off = 0;
- frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
- frag->msg_header.is_ccs = is_ccs;
-
- /* save current state*/
- frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
- frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
- frag->msg_header.saved_retransmit_state.compress = s->compress;
- frag->msg_header.saved_retransmit_state.session = s->session;
- frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
-
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
- frag->msg_header.is_ccs)>>8);
- seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
- frag->msg_header.is_ccs));
-
- item = pitem_new(seq64be, frag);
- if ( item == NULL)
- {
- dtls1_hm_fragment_free(frag);
- return 0;
- }
+int dtls1_retransmit_buffered_messages(SSL *s)
+{
+ pqueue sent = s->d1->sent_messages;
+ piterator iter;
+ pitem *item;
+ hm_fragment *frag;
+ int found = 0;
+
+ iter = pqueue_iterator(sent);
+
+ for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
+ frag = (hm_fragment *)item->data;
+ if (dtls1_retransmit_message(s, (unsigned short)
+ dtls1_get_queue_priority
+ (frag->msg_header.seq,
+ frag->msg_header.is_ccs), 0,
+ &found) <= 0 && found) {
+ fprintf(stderr, "dtls1_retransmit_message() failed\n");
+ return -1;
+ }
+ }
+
+ return 1;
+}
+int dtls1_buffer_message(SSL *s, int is_ccs)
+{
+ pitem *item;
+ hm_fragment *frag;
+ unsigned char seq64be[8];
+
+ /*
+ * this function is called immediately after a message has been
+ * serialized
+ */
+ OPENSSL_assert(s->init_off == 0);
+
+ frag = dtls1_hm_fragment_new(s->init_num, 0);
+ if (!frag)
+ return 0;
+
+ memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+ if (is_ccs) {
+ OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
+ ((s->version ==
+ DTLS1_VERSION) ? DTLS1_CCS_HEADER_LENGTH : 3) ==
+ (unsigned int)s->init_num);
+ } else {
+ OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
+ DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
+ }
+
+ frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.seq = s->d1->w_msg_hdr.seq;
+ frag->msg_header.type = s->d1->w_msg_hdr.type;
+ frag->msg_header.frag_off = 0;
+ frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.is_ccs = is_ccs;
+
+ /* save current state */
+ frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
+ frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
+ frag->msg_header.saved_retransmit_state.compress = s->compress;
+ frag->msg_header.saved_retransmit_state.session = s->session;
+ frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
+
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs) >> 8);
+ seq64be[7] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs));
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ dtls1_hm_fragment_free(frag);
+ return 0;
+ }
#if 0
- fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
- fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
- fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
+ fprintf(stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
+ fprintf(stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
+ fprintf(stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
#endif
- pqueue_insert(s->d1->sent_messages, item);
- return 1;
- }
+ pqueue_insert(s->d1->sent_messages, item);
+ return 1;
+}
int
dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
- int *found)
- {
- int ret;
- /* XDTLS: for now assuming that read/writes are blocking */
- pitem *item;
- hm_fragment *frag ;
- unsigned long header_length;
- unsigned char seq64be[8];
- struct dtls1_retransmit_state saved_state;
- unsigned char save_write_sequence[8];
-
- /*
- OPENSSL_assert(s->init_num == 0);
- OPENSSL_assert(s->init_off == 0);
- */
-
- /* XDTLS: the requested message ought to be found, otherwise error */
- memset(seq64be,0,sizeof(seq64be));
- seq64be[6] = (unsigned char)(seq>>8);
- seq64be[7] = (unsigned char)seq;
-
- item = pqueue_find(s->d1->sent_messages, seq64be);
- if ( item == NULL)
- {
- fprintf(stderr, "retransmit: message %d non-existant\n", seq);
- *found = 0;
- return 0;
- }
-
- *found = 1;
- frag = (hm_fragment *)item->data;
-
- if ( frag->msg_header.is_ccs)
- header_length = DTLS1_CCS_HEADER_LENGTH;
- else
- header_length = DTLS1_HM_HEADER_LENGTH;
-
- memcpy(s->init_buf->data, frag->fragment,
- frag->msg_header.msg_len + header_length);
- s->init_num = frag->msg_header.msg_len + header_length;
-
- dtls1_set_message_header_int(s, frag->msg_header.type,
- frag->msg_header.msg_len, frag->msg_header.seq, 0,
- frag->msg_header.frag_len);
-
- /* save current state */
- saved_state.enc_write_ctx = s->enc_write_ctx;
- saved_state.write_hash = s->write_hash;
- saved_state.compress = s->compress;
- saved_state.session = s->session;
- saved_state.epoch = s->d1->w_epoch;
- saved_state.epoch = s->d1->w_epoch;
-
- s->d1->retransmitting = 1;
-
- /* restore state in which the message was originally sent */
- s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
- s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
- s->compress = frag->msg_header.saved_retransmit_state.compress;
- s->session = frag->msg_header.saved_retransmit_state.session;
- s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
-
- if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
- {
- memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
- memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
- }
-
- ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
- SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
-
- /* restore current state */
- s->enc_write_ctx = saved_state.enc_write_ctx;
- s->write_hash = saved_state.write_hash;
- s->compress = saved_state.compress;
- s->session = saved_state.session;
- s->d1->w_epoch = saved_state.epoch;
-
- if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
- {
- memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
- memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
- }
-
- s->d1->retransmitting = 0;
-
- (void)BIO_flush(SSL_get_wbio(s));
- return ret;
- }
+ int *found)
+{
+ int ret;
+ /* XDTLS: for now assuming that read/writes are blocking */
+ pitem *item;
+ hm_fragment *frag;
+ unsigned long header_length;
+ unsigned char seq64be[8];
+ struct dtls1_retransmit_state saved_state;
+ unsigned char save_write_sequence[8];
+
+ /*-
+ OPENSSL_assert(s->init_num == 0);
+ OPENSSL_assert(s->init_off == 0);
+ */
+
+ /* XDTLS: the requested message ought to be found, otherwise error */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(seq >> 8);
+ seq64be[7] = (unsigned char)seq;
+
+ item = pqueue_find(s->d1->sent_messages, seq64be);
+ if (item == NULL) {
+ fprintf(stderr, "retransmit: message %d non-existant\n", seq);
+ *found = 0;
+ return 0;
+ }
+
+ *found = 1;
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.is_ccs)
+ header_length = DTLS1_CCS_HEADER_LENGTH;
+ else
+ header_length = DTLS1_HM_HEADER_LENGTH;
+
+ memcpy(s->init_buf->data, frag->fragment,
+ frag->msg_header.msg_len + header_length);
+ s->init_num = frag->msg_header.msg_len + header_length;
+
+ dtls1_set_message_header_int(s, frag->msg_header.type,
+ frag->msg_header.msg_len,
+ frag->msg_header.seq, 0,
+ frag->msg_header.frag_len);
+
+ /* save current state */
+ saved_state.enc_write_ctx = s->enc_write_ctx;
+ saved_state.write_hash = s->write_hash;
+ saved_state.compress = s->compress;
+ saved_state.session = s->session;
+ saved_state.epoch = s->d1->w_epoch;
+ saved_state.epoch = s->d1->w_epoch;
+
+ s->d1->retransmitting = 1;
+
+ /* restore state in which the message was originally sent */
+ s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
+ s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
+ s->compress = frag->msg_header.saved_retransmit_state.compress;
+ s->session = frag->msg_header.saved_retransmit_state.session;
+ s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
+
+ if (frag->msg_header.saved_retransmit_state.epoch ==
+ saved_state.epoch - 1) {
+ memcpy(save_write_sequence, s->s3->write_sequence,
+ sizeof(s->s3->write_sequence));
+ memcpy(s->s3->write_sequence, s->d1->last_write_sequence,
+ sizeof(s->s3->write_sequence));
+ }
+
+ ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
+ SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+
+ /* restore current state */
+ s->enc_write_ctx = saved_state.enc_write_ctx;
+ s->write_hash = saved_state.write_hash;
+ s->compress = saved_state.compress;
+ s->session = saved_state.session;
+ s->d1->w_epoch = saved_state.epoch;
+
+ if (frag->msg_header.saved_retransmit_state.epoch ==
+ saved_state.epoch - 1) {
+ memcpy(s->d1->last_write_sequence, s->s3->write_sequence,
+ sizeof(s->s3->write_sequence));
+ memcpy(s->s3->write_sequence, save_write_sequence,
+ sizeof(s->s3->write_sequence));
+ }
+
+ s->d1->retransmitting = 0;
+
+ (void)BIO_flush(SSL_get_wbio(s));
+ return ret;
+}
/* call this function when the buffered messages are no longer needed */
-void
-dtls1_clear_record_buffer(SSL *s)
- {
- pitem *item;
-
- for(item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages))
- {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
- }
-
+void dtls1_clear_record_buffer(SSL *s)
+{
+ pitem *item;
-unsigned char *
-dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
- unsigned long len, unsigned long frag_off, unsigned long frag_len)
- {
- /* Don't change sequence numbers while listening */
- if (frag_off == 0 && !s->d1->listen)
- {
- s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
- s->d1->next_handshake_write_seq++;
- }
+ for (item = pqueue_pop(s->d1->sent_messages);
+ item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
+ dtls1_hm_fragment_free((hm_fragment *)item->data);
+ pitem_free(item);
+ }
+}
- dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
- frag_off, frag_len);
+unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
+ unsigned char mt, unsigned long len,
+ unsigned long frag_off,
+ unsigned long frag_len)
+{
+ /* Don't change sequence numbers while listening */
+ if (frag_off == 0 && !s->d1->listen) {
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->d1->next_handshake_write_seq++;
+ }
- return p += DTLS1_HM_HEADER_LENGTH;
- }
+ dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
+ frag_off, frag_len);
+ return p += DTLS1_HM_HEADER_LENGTH;
+}
/* don't actually do the writing, wait till the MTU has been retrieved */
static void
dtls1_set_message_header_int(SSL *s, unsigned char mt,
- unsigned long len, unsigned short seq_num, unsigned long frag_off,
- unsigned long frag_len)
- {
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-
- msg_hdr->type = mt;
- msg_hdr->msg_len = len;
- msg_hdr->seq = seq_num;
- msg_hdr->frag_off = frag_off;
- msg_hdr->frag_len = frag_len;
- }
+ unsigned long len, unsigned short seq_num,
+ unsigned long frag_off, unsigned long frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ msg_hdr->type = mt;
+ msg_hdr->msg_len = len;
+ msg_hdr->seq = seq_num;
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
static void
dtls1_fix_message_header(SSL *s, unsigned long frag_off,
- unsigned long frag_len)
- {
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-
- msg_hdr->frag_off = frag_off;
- msg_hdr->frag_len = frag_len;
- }
+ unsigned long frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-static unsigned char *
-dtls1_write_message_header(SSL *s, unsigned char *p)
- {
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
- *p++ = msg_hdr->type;
- l2n3(msg_hdr->msg_len, p);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
- s2n(msg_hdr->seq, p);
- l2n3(msg_hdr->frag_off, p);
- l2n3(msg_hdr->frag_len, p);
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
- return p;
- }
+ s2n(msg_hdr->seq, p);
+ l2n3(msg_hdr->frag_off, p);
+ l2n3(msg_hdr->frag_len, p);
-unsigned int
-dtls1_link_min_mtu(void)
- {
- return (g_probable_mtu[(sizeof(g_probable_mtu) /
- sizeof(g_probable_mtu[0])) - 1]);
- }
+ return p;
+}
-unsigned int
-dtls1_min_mtu(SSL *s)
- {
- return dtls1_link_min_mtu()-BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
- }
+unsigned int dtls1_link_min_mtu(void)
+{
+ return (g_probable_mtu[(sizeof(g_probable_mtu) /
+ sizeof(g_probable_mtu[0])) - 1]);
+}
+unsigned int dtls1_min_mtu(SSL *s)
+{
+ return dtls1_link_min_mtu() - BIO_dgram_get_mtu_overhead(SSL_get_wbio(s));
+}
void
dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
- {
- memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
- msg_hdr->type = *(data++);
- n2l3(data, msg_hdr->msg_len);
+{
+ memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+ msg_hdr->type = *(data++);
+ n2l3(data, msg_hdr->msg_len);
- n2s(data, msg_hdr->seq);
- n2l3(data, msg_hdr->frag_off);
- n2l3(data, msg_hdr->frag_len);
- }
+ n2s(data, msg_hdr->seq);
+ n2l3(data, msg_hdr->frag_off);
+ n2l3(data, msg_hdr->frag_len);
+}
-void
-dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
- {
- memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
+void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
+{
+ memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
- ccs_hdr->type = *(data++);
- }
+ ccs_hdr->type = *(data++);
+}
int dtls1_shutdown(SSL *s)
- {
- int ret;
+{
+ int ret;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
- !(s->shutdown & SSL_SENT_SHUTDOWN))
- {
- ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
- if (ret < 0) return -1;
-
- if (ret == 0)
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, NULL);
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ !(s->shutdown & SSL_SENT_SHUTDOWN)) {
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0)
+ return -1;
+
+ if (ret == 0)
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1,
+ NULL);
+ }
#endif
- ret = ssl3_shutdown(s);
+ ret = ssl3_shutdown(s);
#ifndef OPENSSL_NO_SCTP
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
#endif
- return ret;
- }
+ return ret;
+}
#ifndef OPENSSL_NO_HEARTBEATS
-int
-dtls1_process_heartbeat(SSL *s)
- {
- unsigned char *p = &s->s3->rrec.data[0], *pl;
- unsigned short hbtype;
- unsigned int payload;
- unsigned int padding = 16; /* Use minimum padding */
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
- &s->s3->rrec.data[0], s->s3->rrec.length,
- s, s->msg_callback_arg);
-
- /* Read type and payload length first */
- if (1 + 2 + 16 > s->s3->rrec.length)
- return 0; /* silently discard */
- if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)
- return 0; /* silently discard per RFC 6520 sec. 4 */
-
- hbtype = *p++;
- n2s(p, payload);
- if (1 + 2 + payload + 16 > s->s3->rrec.length)
- return 0; /* silently discard per RFC 6520 sec. 4 */
- pl = p;
-
- if (hbtype == TLS1_HB_REQUEST)
- {
- unsigned char *buffer, *bp;
- unsigned int write_length = 1 /* heartbeat type */ +
- 2 /* heartbeat length */ +
- payload + padding;
- int r;
-
- if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
- return 0;
-
- /* Allocate memory for the response, size is 1 byte
- * message type, plus 2 bytes payload length, plus
- * payload, plus padding
- */
- buffer = OPENSSL_malloc(write_length);
- bp = buffer;
-
- /* Enter response type, length and copy payload */
- *bp++ = TLS1_HB_RESPONSE;
- s2n(payload, bp);
- memcpy(bp, pl, payload);
- bp += payload;
- /* Random padding */
- RAND_pseudo_bytes(bp, padding);
-
- r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
-
- if (r >= 0 && s->msg_callback)
- s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
- buffer, write_length,
- s, s->msg_callback_arg);
-
- OPENSSL_free(buffer);
-
- if (r < 0)
- return r;
- }
- else if (hbtype == TLS1_HB_RESPONSE)
- {
- unsigned int seq;
-
- /* We only send sequence numbers (2 bytes unsigned int),
- * and 16 random bytes, so we just try to read the
- * sequence number */
- n2s(pl, seq);
-
- if (payload == 18 && seq == s->tlsext_hb_seq)
- {
- dtls1_stop_timer(s);
- s->tlsext_hb_seq++;
- s->tlsext_hb_pending = 0;
- }
- }
-
- return 0;
- }
+int dtls1_process_heartbeat(SSL *s)
+{
+ unsigned char *p = &s->s3->rrec.data[0], *pl;
+ unsigned short hbtype;
+ unsigned int payload;
+ unsigned int padding = 16; /* Use minimum padding */
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
+ &s->s3->rrec.data[0], s->s3->rrec.length,
+ s, s->msg_callback_arg);
+
+ /* Read type and payload length first */
+ if (1 + 2 + 16 > s->s3->rrec.length)
+ return 0; /* silently discard */
+ if (s->s3->rrec.length > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+
+ hbtype = *p++;
+ n2s(p, payload);
+ if (1 + 2 + payload + 16 > s->s3->rrec.length)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+ pl = p;
+
+ if (hbtype == TLS1_HB_REQUEST) {
+ unsigned char *buffer, *bp;
+ unsigned int write_length = 1 /* heartbeat type */ +
+ 2 /* heartbeat length */ +
+ payload + padding;
+ int r;
+
+ if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+
+ /*
+ * Allocate memory for the response, size is 1 byte message type,
+ * plus 2 bytes payload length, plus payload, plus padding
+ */
+ buffer = OPENSSL_malloc(write_length);
+ bp = buffer;
+
+ /* Enter response type, length and copy payload */
+ *bp++ = TLS1_HB_RESPONSE;
+ s2n(payload, bp);
+ memcpy(bp, pl, payload);
+ bp += payload;
+ /* Random padding */
+ RAND_pseudo_bytes(bp, padding);
+
+ r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
+
+ if (r >= 0 && s->msg_callback)
+ s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
+ buffer, write_length, s, s->msg_callback_arg);
+
+ OPENSSL_free(buffer);
+
+ if (r < 0)
+ return r;
+ } else if (hbtype == TLS1_HB_RESPONSE) {
+ unsigned int seq;
+
+ /*
+ * We only send sequence numbers (2 bytes unsigned int), and 16
+ * random bytes, so we just try to read the sequence number
+ */
+ n2s(pl, seq);
+
+ if (payload == 18 && seq == s->tlsext_hb_seq) {
+ dtls1_stop_timer(s);
+ s->tlsext_hb_seq++;
+ s->tlsext_hb_pending = 0;
+ }
+ }
+
+ return 0;
+}
-int
-dtls1_heartbeat(SSL *s)
- {
- unsigned char *buf, *p;
- int ret;
- unsigned int payload = 18; /* Sequence number + random bytes */
- unsigned int padding = 16; /* Use minimum padding */
-
- /* Only send if peer supports and accepts HB requests... */
- if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
- s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS)
- {
- SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
- return -1;
- }
-
- /* ...and there is none in flight yet... */
- if (s->tlsext_hb_pending)
- {
- SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PENDING);
- return -1;
- }
-
- /* ...and no handshake in progress. */
- if (SSL_in_init(s) || s->in_handshake)
- {
- SSLerr(SSL_F_DTLS1_HEARTBEAT,SSL_R_UNEXPECTED_MESSAGE);
- return -1;
- }
-
- /* Check if padding is too long, payload and padding
- * must not exceed 2^14 - 3 = 16381 bytes in total.
- */
- OPENSSL_assert(payload + padding <= 16381);
-
- /* Create HeartBeat message, we just use a sequence number
- * as payload to distuingish different messages and add
- * some random stuff.
- * - Message Type, 1 byte
- * - Payload Length, 2 bytes (unsigned int)
- * - Payload, the sequence number (2 bytes uint)
- * - Payload, random bytes (16 bytes uint)
- * - Padding
- */
- buf = OPENSSL_malloc(1 + 2 + payload + padding);
- p = buf;
- /* Message Type */
- *p++ = TLS1_HB_REQUEST;
- /* Payload length (18 bytes here) */
- s2n(payload, p);
- /* Sequence number */
- s2n(s->tlsext_hb_seq, p);
- /* 16 random bytes */
- RAND_pseudo_bytes(p, 16);
- p += 16;
- /* Random padding */
- RAND_pseudo_bytes(p, padding);
-
- ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
- if (ret >= 0)
- {
- if (s->msg_callback)
- s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
- buf, 3 + payload + padding,
- s, s->msg_callback_arg);
-
- dtls1_start_timer(s);
- s->tlsext_hb_pending = 1;
- }
-
- OPENSSL_free(buf);
-
- return ret;
- }
+int dtls1_heartbeat(SSL *s)
+{
+ unsigned char *buf, *p;
+ int ret;
+ unsigned int payload = 18; /* Sequence number + random bytes */
+ unsigned int padding = 16; /* Use minimum padding */
+
+ /* Only send if peer supports and accepts HB requests... */
+ if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) ||
+ s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT);
+ return -1;
+ }
+
+ /* ...and there is none in flight yet... */
+ if (s->tlsext_hb_pending) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_TLS_HEARTBEAT_PENDING);
+ return -1;
+ }
+
+ /* ...and no handshake in progress. */
+ if (SSL_in_init(s) || s->in_handshake) {
+ SSLerr(SSL_F_DTLS1_HEARTBEAT, SSL_R_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ /*
+ * Check if padding is too long, payload and padding must not exceed 2^14
+ * - 3 = 16381 bytes in total.
+ */
+ OPENSSL_assert(payload + padding <= 16381);
+
+ /*-
+ * Create HeartBeat message, we just use a sequence number
+ * as payload to distuingish different messages and add
+ * some random stuff.
+ * - Message Type, 1 byte
+ * - Payload Length, 2 bytes (unsigned int)
+ * - Payload, the sequence number (2 bytes uint)
+ * - Payload, random bytes (16 bytes uint)
+ * - Padding
+ */
+ buf = OPENSSL_malloc(1 + 2 + payload + padding);
+ p = buf;
+ /* Message Type */
+ *p++ = TLS1_HB_REQUEST;
+ /* Payload length (18 bytes here) */
+ s2n(payload, p);
+ /* Sequence number */
+ s2n(s->tlsext_hb_seq, p);
+ /* 16 random bytes */
+ RAND_pseudo_bytes(p, 16);
+ p += 16;
+ /* Random padding */
+ RAND_pseudo_bytes(p, padding);
+
+ ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
+ if (ret >= 0) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
+ buf, 3 + payload + padding,
+ s, s->msg_callback_arg);
+
+ dtls1_start_timer(s);
+ s->tlsext_hb_pending = 1;
+ }
+
+ OPENSSL_free(buf);
+
+ return ret;
+}
#endif
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 9045fb9902f5..1394781c047a 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -1,7 +1,7 @@
/* ssl/d1_clnt.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,21 +62,21 @@
* 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:
@@ -91,10 +91,10 @@
* 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
+ * 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
@@ -106,7 +106,7 @@
* 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
@@ -116,7 +116,7 @@
#include <stdio.h>
#include "ssl_locl.h"
#ifndef OPENSSL_NO_KRB5
-#include "kssl_lcl.h"
+# include "kssl_lcl.h"
#endif
#include <openssl/buffer.h>
#include <openssl/rand.h>
@@ -125,1612 +125,1568 @@
#include <openssl/md5.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_DH
-#include <openssl/dh.h>
+# include <openssl/dh.h>
#endif
static const SSL_METHOD *dtls1_get_client_method(int ver);
static int dtls1_get_hello_verify(SSL *s);
static const SSL_METHOD *dtls1_get_client_method(int ver)
- {
- if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
- return(DTLSv1_client_method());
- else
- return(NULL);
- }
+{
+ if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
+ return (DTLSv1_client_method());
+ else
+ return (NULL);
+}
IMPLEMENT_dtls1_meth_func(DTLSv1_client_method,
- ssl_undefined_function,
- dtls1_connect,
- dtls1_get_client_method)
+ ssl_undefined_function,
+ dtls1_connect, dtls1_get_client_method)
int dtls1_connect(SSL *s)
- {
- BUF_MEM *buf=NULL;
- unsigned long Time=(unsigned long)time(NULL);
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- int ret= -1;
- int new_state,state,skip=0;
+{
+ BUF_MEM *buf = NULL;
+ unsigned long Time = (unsigned long)time(NULL);
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ int ret = -1;
+ int new_state, state, skip = 0;
#ifndef OPENSSL_NO_SCTP
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif
- RAND_add(&Time,sizeof(Time),0);
- ERR_clear_error();
- clear_sys_error();
+ RAND_add(&Time, sizeof(Time), 0);
+ ERR_clear_error();
+ clear_sys_error();
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- s->in_handshake++;
- if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ s->in_handshake++;
+ if (!SSL_in_init(s) || SSL_in_before(s))
+ SSL_clear(s);
#ifndef OPENSSL_NO_SCTP
- /* Notify SCTP BIO socket to enter handshake
- * mode and prevent stream identifier other
- * than 0. Will be ignored if no SCTP is used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL);
+ /*
+ * Notify SCTP BIO socket to enter handshake mode and prevent stream
+ * identifier other than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ s->in_handshake, NULL);
#endif
#ifndef OPENSSL_NO_HEARTBEATS
- /* If we're awaiting a HeartbeatResponse, pretend we
- * already got and don't await it anymore, because
- * Heartbeats don't make sense during handshakes anyway.
- */
- if (s->tlsext_hb_pending)
- {
- dtls1_stop_timer(s);
- s->tlsext_hb_pending = 0;
- s->tlsext_hb_seq++;
- }
+ /*
+ * If we're awaiting a HeartbeatResponse, pretend we already got and
+ * don't await it anymore, because Heartbeats don't make sense during
+ * handshakes anyway.
+ */
+ if (s->tlsext_hb_pending) {
+ dtls1_stop_timer(s);
+ s->tlsext_hb_pending = 0;
+ s->tlsext_hb_seq++;
+ }
#endif
- for (;;)
- {
- state=s->state;
-
- switch(s->state)
- {
- case SSL_ST_RENEGOTIATE:
- s->renegotiate=1;
- s->state=SSL_ST_CONNECT;
- s->ctx->stats.sess_connect_renegotiate++;
- /* break */
- case SSL_ST_BEFORE:
- case SSL_ST_CONNECT:
- case SSL_ST_BEFORE|SSL_ST_CONNECT:
- case SSL_ST_OK|SSL_ST_CONNECT:
-
- s->server=0;
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
-
- if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
- (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
- {
- SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
- ret = -1;
- goto end;
- }
-
- /* s->version=SSL3_VERSION; */
- s->type=SSL_ST_CONNECT;
-
- if (s->init_buf == NULL)
- {
- if ((buf=BUF_MEM_new()) == NULL)
- {
- ret= -1;
- goto end;
- }
- if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
- {
- ret= -1;
- goto end;
- }
- s->init_buf=buf;
- buf=NULL;
- }
-
- if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
-
- /* setup buffing BIO */
- if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
-
- /* don't push the buffering BIO quite yet */
-
- s->state=SSL3_ST_CW_CLNT_HELLO_A;
- s->ctx->stats.sess_connect++;
- s->init_num=0;
- /* mark client_random uninitialized */
- memset(s->s3->client_random,0,sizeof(s->s3->client_random));
- s->d1->send_cookie = 0;
- s->hit = 0;
- s->d1->change_cipher_spec_ok = 0;
- /* Should have been reset by ssl3_get_finished, too. */
- s->s3->change_cipher_spec = 0;
- break;
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ s->state = SSL_ST_CONNECT;
+ s->ctx->stats.sess_connect_renegotiate++;
+ /* break */
+ case SSL_ST_BEFORE:
+ case SSL_ST_CONNECT:
+ case SSL_ST_BEFORE | SSL_ST_CONNECT:
+ case SSL_ST_OK | SSL_ST_CONNECT:
+
+ s->server = 0;
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+
+ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
+ (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00)) {
+ SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
+
+ /* s->version=SSL3_VERSION; */
+ s->type = SSL_ST_CONNECT;
+
+ if (s->init_buf == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL) {
+ ret = -1;
+ goto end;
+ }
+ if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ /* setup buffing BIO */
+ if (!ssl_init_wbio_buffer(s, 0)) {
+ ret = -1;
+ goto end;
+ }
+
+ /* don't push the buffering BIO quite yet */
+
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ s->ctx->stats.sess_connect++;
+ s->init_num = 0;
+ /* mark client_random uninitialized */
+ memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
+ s->d1->send_cookie = 0;
+ s->hit = 0;
+ s->d1->change_cipher_spec_ok = 0;
+ /*
+ * Should have been reset by ssl3_get_finished, too.
+ */
+ s->s3->change_cipher_spec = 0;
+ break;
#ifndef OPENSSL_NO_SCTP
- case DTLS1_SCTP_ST_CR_READ_SOCK:
-
- if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
- {
- s->s3->in_read_app_data=2;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- ret = -1;
- goto end;
- }
-
- s->state=s->s3->tmp.next_state;
- break;
-
- case DTLS1_SCTP_ST_CW_WRITE_SOCK:
- /* read app data until dry event */
-
- ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
- if (ret < 0) goto end;
-
- if (ret == 0)
- {
- s->s3->in_read_app_data=2;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- ret = -1;
- goto end;
- }
-
- s->state=s->d1->next_state;
- break;
+ case DTLS1_SCTP_ST_CR_READ_SOCK:
+
+ if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case DTLS1_SCTP_ST_CW_WRITE_SOCK:
+ /* read app data until dry event */
+
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0)
+ goto end;
+
+ if (ret == 0) {
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state = s->d1->next_state;
+ break;
#endif
- case SSL3_ST_CW_CLNT_HELLO_A:
- case SSL3_ST_CW_CLNT_HELLO_B:
+ case SSL3_ST_CW_CLNT_HELLO_A:
+ case SSL3_ST_CW_CLNT_HELLO_B:
- s->shutdown=0;
+ s->shutdown = 0;
- /* every DTLS ClientHello resets Finished MAC */
- ssl3_init_finished_mac(s);
+ /* every DTLS ClientHello resets Finished MAC */
+ ssl3_init_finished_mac(s);
- dtls1_start_timer(s);
- ret=dtls1_client_hello(s);
- if (ret <= 0) goto end;
+ dtls1_start_timer(s);
+ ret = dtls1_client_hello(s);
+ if (ret <= 0)
+ goto end;
- if ( s->d1->send_cookie)
- {
- s->state=SSL3_ST_CW_FLUSH;
- s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A;
- }
- else
- s->state=SSL3_ST_CR_SRVR_HELLO_A;
+ if (s->d1->send_cookie) {
+ s->state = SSL3_ST_CW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
+ } else
+ s->state = SSL3_ST_CR_SRVR_HELLO_A;
- s->init_num=0;
+ s->init_num = 0;
#ifndef OPENSSL_NO_SCTP
- /* Disable buffering for SCTP */
- if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
+ /* Disable buffering for SCTP */
+ if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) {
#endif
- /* turn on buffering for the next lot of output */
- if (s->bbio != s->wbio)
- s->wbio=BIO_push(s->bbio,s->wbio);
+ /*
+ * turn on buffering for the next lot of output
+ */
+ if (s->bbio != s->wbio)
+ s->wbio = BIO_push(s->bbio, s->wbio);
#ifndef OPENSSL_NO_SCTP
- }
+ }
#endif
- break;
+ break;
- case SSL3_ST_CR_SRVR_HELLO_A:
- case SSL3_ST_CR_SRVR_HELLO_B:
- ret=ssl3_get_server_hello(s);
- if (ret <= 0) goto end;
- else
- {
- if (s->hit)
- {
+ case SSL3_ST_CR_SRVR_HELLO_A:
+ case SSL3_ST_CR_SRVR_HELLO_B:
+ ret = ssl3_get_server_hello(s);
+ if (ret <= 0)
+ goto end;
+ else {
+ if (s->hit) {
#ifndef OPENSSL_NO_SCTP
- /* Add new shared key for SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
- DTLS1_SCTP_AUTH_LABEL);
-
- SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ snprintf((char *)labelbuffer,
+ sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey),
+ labelbuffer,
+ sizeof(labelbuffer), NULL, 0,
+ 0);
+
+ BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
#endif
- s->state=SSL3_ST_CR_FINISHED_A;
- }
- else
- s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
- }
- s->init_num=0;
- break;
-
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
- case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
-
- ret = dtls1_get_hello_verify(s);
- if ( ret <= 0)
- goto end;
- dtls1_stop_timer(s);
- if ( s->d1->send_cookie) /* start again, with a cookie */
- s->state=SSL3_ST_CW_CLNT_HELLO_A;
- 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:
- /* Check if it is anon DH or PSK */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
- !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
- {
- ret=ssl3_get_server_certificate(s);
- if (ret <= 0) goto end;
+ s->state = SSL3_ST_CR_FINISHED_A;
+ } else
+ s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
+ }
+ s->init_num = 0;
+ break;
+
+ case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
+ case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
+
+ ret = dtls1_get_hello_verify(s);
+ if (ret <= 0)
+ goto end;
+ dtls1_stop_timer(s);
+ if (s->d1->send_cookie) /* start again, with a cookie */
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ 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:
+ /* Check if it is anon DH or PSK */
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ ret = ssl3_get_server_certificate(s);
+ if (ret <= 0)
+ goto end;
#ifndef OPENSSL_NO_TLSEXT
- if (s->tlsext_status_expected)
- s->state=SSL3_ST_CR_CERT_STATUS_A;
- else
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- }
- else
- {
- skip = 1;
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- }
+ if (s->tlsext_status_expected)
+ s->state = SSL3_ST_CR_CERT_STATUS_A;
+ else
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ } else {
+ skip = 1;
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
#else
- }
- else
- skip=1;
+ } else
+ skip = 1;
- s->state=SSL3_ST_CR_KEY_EXCH_A;
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
#endif
- s->init_num=0;
- break;
-
- case SSL3_ST_CR_KEY_EXCH_A:
- case SSL3_ST_CR_KEY_EXCH_B:
- ret=ssl3_get_key_exchange(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_CERT_REQ_A;
- s->init_num=0;
-
- /* at this point we check that we have the
- * required stuff from the server */
- if (!ssl3_check_cert_and_algorithm(s))
- {
- ret= -1;
- goto end;
- }
- break;
-
- case SSL3_ST_CR_CERT_REQ_A:
- case SSL3_ST_CR_CERT_REQ_B:
- ret=ssl3_get_certificate_request(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_SRVR_DONE_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_CR_SRVR_DONE_A:
- case SSL3_ST_CR_SRVR_DONE_B:
- ret=ssl3_get_server_done(s);
- if (ret <= 0) goto end;
- dtls1_stop_timer(s);
- if (s->s3->tmp.cert_req)
- s->s3->tmp.next_state=SSL3_ST_CW_CERT_A;
- else
- s->s3->tmp.next_state=SSL3_ST_CW_KEY_EXCH_A;
- s->init_num=0;
-
-#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
- state == SSL_ST_RENEGOTIATE)
- s->state=DTLS1_SCTP_ST_CR_READ_SOCK;
- else
-#endif
- s->state=s->s3->tmp.next_state;
- break;
-
- case SSL3_ST_CW_CERT_A:
- case SSL3_ST_CW_CERT_B:
- case SSL3_ST_CW_CERT_C:
- case SSL3_ST_CW_CERT_D:
- dtls1_start_timer(s);
- ret=dtls1_send_client_certificate(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_KEY_EXCH_A;
- s->init_num=0;
- break;
-
- 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);
- if (ret <= 0) goto end;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_KEY_EXCH_A:
+ case SSL3_ST_CR_KEY_EXCH_B:
+ ret = ssl3_get_key_exchange(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CR_CERT_REQ_A;
+ s->init_num = 0;
+
+ /*
+ * at this point we check that we have the required stuff from
+ * the server
+ */
+ if (!ssl3_check_cert_and_algorithm(s)) {
+ ret = -1;
+ goto end;
+ }
+ break;
+
+ case SSL3_ST_CR_CERT_REQ_A:
+ case SSL3_ST_CR_CERT_REQ_B:
+ ret = ssl3_get_certificate_request(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CR_SRVR_DONE_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_SRVR_DONE_A:
+ case SSL3_ST_CR_SRVR_DONE_B:
+ ret = ssl3_get_server_done(s);
+ if (ret <= 0)
+ goto end;
+ dtls1_stop_timer(s);
+ if (s->s3->tmp.cert_req)
+ s->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
+ else
+ s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
+ s->init_num = 0;
#ifndef OPENSSL_NO_SCTP
- /* Add new shared key for SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
- DTLS1_SCTP_AUTH_LABEL);
-
- SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ state == SSL_ST_RENEGOTIATE)
+ s->state = DTLS1_SCTP_ST_CR_READ_SOCK;
+ else
#endif
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL3_ST_CW_CERT_A:
+ case SSL3_ST_CW_CERT_B:
+ case SSL3_ST_CW_CERT_C:
+ case SSL3_ST_CW_CERT_D:
+ dtls1_start_timer(s);
+ ret = dtls1_send_client_certificate(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CW_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
+
+ 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);
+ if (ret <= 0)
+ goto end;
- /* EAY EAY EAY need to check for DH fix cert
- * sent back */
- /* For TLS, cert_req is set to 2, so a cert chain
- * of nothing is sent, but no verify packet is sent */
- if (s->s3->tmp.cert_req == 1)
- {
- s->state=SSL3_ST_CW_CERT_VRFY_A;
- }
- else
- {
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state=SSL3_ST_CW_CHANGE_A;
- s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
- }
- else
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0);
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
#endif
- s->state=SSL3_ST_CW_CHANGE_A;
- }
-
- s->init_num=0;
- break;
- case SSL3_ST_CW_CERT_VRFY_A:
- case SSL3_ST_CW_CERT_VRFY_B:
- dtls1_start_timer(s);
- ret=dtls1_send_client_verify(s);
- if (ret <= 0) goto end;
+ /*
+ * EAY EAY EAY need to check for DH fix cert sent back
+ */
+ /*
+ * For TLS, cert_req is set to 2, so a cert chain of nothing is
+ * sent, but no verify packet is sent
+ */
+ if (s->s3->tmp.cert_req == 1) {
+ s->state = SSL3_ST_CW_CERT_VRFY_A;
+ } else {
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state=SSL3_ST_CW_CHANGE_A;
- s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
- }
- else
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = SSL3_ST_CW_CHANGE_A;
+ s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ } else
#endif
- s->state=SSL3_ST_CW_CHANGE_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_CW_CHANGE_A:
- case SSL3_ST_CW_CHANGE_B:
- if (!s->hit)
- dtls1_start_timer(s);
- ret=dtls1_send_change_cipher_spec(s,
- SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
- if (ret <= 0) goto end;
-
- s->state=SSL3_ST_CW_FINISHED_A;
- s->init_num=0;
-
- s->session->cipher=s->s3->tmp.new_cipher;
+ s->state = SSL3_ST_CW_CHANGE_A;
+ }
+
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CW_CERT_VRFY_A:
+ case SSL3_ST_CW_CERT_VRFY_B:
+ dtls1_start_timer(s);
+ ret = dtls1_send_client_verify(s);
+ if (ret <= 0)
+ goto end;
+#ifndef OPENSSL_NO_SCTP
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = SSL3_ST_CW_CHANGE_A;
+ s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ } else
+#endif
+ s->state = SSL3_ST_CW_CHANGE_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CW_CHANGE_A:
+ case SSL3_ST_CW_CHANGE_B:
+ if (!s->hit)
+ dtls1_start_timer(s);
+ ret = dtls1_send_change_cipher_spec(s,
+ SSL3_ST_CW_CHANGE_A,
+ SSL3_ST_CW_CHANGE_B);
+ if (ret <= 0)
+ goto end;
+
+ s->state = SSL3_ST_CW_FINISHED_A;
+ s->init_num = 0;
+
+ s->session->cipher = s->s3->tmp.new_cipher;
#ifdef OPENSSL_NO_COMP
- s->session->compress_meth=0;
+ s->session->compress_meth = 0;
#else
- if (s->s3->tmp.new_compression == NULL)
- s->session->compress_meth=0;
- else
- s->session->compress_meth=
- s->s3->tmp.new_compression->id;
+ if (s->s3->tmp.new_compression == NULL)
+ s->session->compress_meth = 0;
+ else
+ s->session->compress_meth = s->s3->tmp.new_compression->id;
#endif
- if (!s->method->ssl3_enc->setup_key_block(s))
- {
- ret= -1;
- goto end;
- }
-
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CHANGE_CIPHER_CLIENT_WRITE))
- {
- ret= -1;
- goto end;
- }
-
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+ {
+ ret = -1;
+ goto end;
+ }
#ifndef OPENSSL_NO_SCTP
- if (s->hit)
- {
- /* Change to new shared key of SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
- }
+ if (s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
#endif
- dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
- break;
-
- case SSL3_ST_CW_FINISHED_A:
- 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);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_FLUSH;
-
- /* clear flags */
- s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
- if (s->hit)
- {
- s->s3->tmp.next_state=SSL_ST_OK;
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ case SSL3_ST_CW_FINISHED_A:
+ 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);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CW_FLUSH;
+
+ /* clear flags */
+ s->s3->flags &= ~SSL3_FLAGS_POP_BUFFER;
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = s->s3->tmp.next_state;
- s->s3->tmp.next_state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
#endif
- if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
- {
- s->state=SSL_ST_OK;
+ if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) {
+ s->state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = SSL_ST_OK;
- s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = SSL_ST_OK;
+ s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
#endif
- s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
- s->s3->delay_buf_pop_ret=0;
- }
- }
- else
- {
+ s->s3->flags |= SSL3_FLAGS_POP_BUFFER;
+ s->s3->delay_buf_pop_ret = 0;
+ }
+ } else {
#ifndef OPENSSL_NO_SCTP
- /* Change to new shared key of SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
#endif
#ifndef OPENSSL_NO_TLSEXT
- /* Allow NewSessionTicket if ticket expected */
- if (s->tlsext_ticket_expected)
- s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
- else
+ /*
+ * Allow NewSessionTicket if ticket expected
+ */
+ if (s->tlsext_ticket_expected)
+ s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+ else
#endif
-
- s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
- }
- s->init_num=0;
- break;
+
+ s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A;
+ }
+ s->init_num = 0;
+ break;
#ifndef OPENSSL_NO_TLSEXT
- case SSL3_ST_CR_SESSION_TICKET_A:
- case SSL3_ST_CR_SESSION_TICKET_B:
- ret=ssl3_get_new_session_ticket(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_FINISHED_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_CR_CERT_STATUS_A:
- case SSL3_ST_CR_CERT_STATUS_B:
- ret=ssl3_get_cert_status(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- s->init_num=0;
- break;
+ case SSL3_ST_CR_SESSION_TICKET_A:
+ case SSL3_ST_CR_SESSION_TICKET_B:
+ ret = ssl3_get_new_session_ticket(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CR_FINISHED_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CR_CERT_STATUS_A:
+ case SSL3_ST_CR_CERT_STATUS_B:
+ ret = ssl3_get_cert_status(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
#endif
- case SSL3_ST_CR_FINISHED_A:
- case SSL3_ST_CR_FINISHED_B:
- s->d1->change_cipher_spec_ok = 1;
- ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
- SSL3_ST_CR_FINISHED_B);
- if (ret <= 0) goto end;
- dtls1_stop_timer(s);
+ case SSL3_ST_CR_FINISHED_A:
+ case SSL3_ST_CR_FINISHED_B:
+ s->d1->change_cipher_spec_ok = 1;
+ ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
+ SSL3_ST_CR_FINISHED_B);
+ if (ret <= 0)
+ goto end;
+ dtls1_stop_timer(s);
- if (s->hit)
- s->state=SSL3_ST_CW_CHANGE_A;
- else
- s->state=SSL_ST_OK;
+ if (s->hit)
+ s->state = SSL3_ST_CW_CHANGE_A;
+ else
+ s->state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
- state == SSL_ST_RENEGOTIATE)
- {
- s->d1->next_state=s->state;
- s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ state == SSL_ST_RENEGOTIATE) {
+ s->d1->next_state = s->state;
+ s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
#endif
- s->init_num=0;
- break;
-
- case SSL3_ST_CW_FLUSH:
- s->rwstate=SSL_WRITING;
- if (BIO_flush(s->wbio) <= 0)
- {
- /* If the write error was fatal, stop trying */
- if (!BIO_should_retry(s->wbio))
- {
- s->rwstate=SSL_NOTHING;
- s->state=s->s3->tmp.next_state;
- }
-
- ret= -1;
- goto end;
- }
- s->rwstate=SSL_NOTHING;
- s->state=s->s3->tmp.next_state;
- break;
-
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(s);
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_CW_FLUSH:
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ /*
+ * If the write error was fatal, stop trying
+ */
+ if (!BIO_should_retry(s->wbio)) {
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ }
+
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
#if 0
- if (s->init_buf != NULL)
- {
- BUF_MEM_free(s->init_buf);
- s->init_buf=NULL;
- }
+ if (s->init_buf != NULL) {
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
#endif
- /* If we are not 'joining' the last two packets,
- * remove the buffering now */
- if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
- ssl_free_wbio_buffer(s);
- /* else do it later in ssl3_write */
-
- s->init_num=0;
- s->renegotiate=0;
- s->new_session=0;
-
- ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
- if (s->hit) s->ctx->stats.sess_hit++;
-
- ret=1;
- /* s->server=0; */
- s->handshake_func=dtls1_connect;
- s->ctx->stats.sess_connect_good++;
-
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
-
- /* done with handshaking */
- s->d1->handshake_read_seq = 0;
- s->d1->next_handshake_write_seq = 0;
- goto end;
- /* break; */
-
- default:
- SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE);
- ret= -1;
- goto end;
- /* break; */
- }
-
- /* did we do anything */
- if (!s->s3->tmp.reuse_message && !skip)
- {
- if (s->debug)
- {
- if ((ret=BIO_flush(s->wbio)) <= 0)
- goto end;
- }
-
- if ((cb != NULL) && (s->state != state))
- {
- new_state=s->state;
- s->state=state;
- cb(s,SSL_CB_CONNECT_LOOP,1);
- s->state=new_state;
- }
- }
- skip=0;
- }
-end:
- s->in_handshake--;
-
+ /*
+ * If we are not 'joining' the last two packets, remove the
+ * buffering now
+ */
+ if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
+ ssl_free_wbio_buffer(s);
+ /* else do it later in ssl3_write */
+
+ s->init_num = 0;
+ s->renegotiate = 0;
+ s->new_session = 0;
+
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ if (s->hit)
+ s->ctx->stats.sess_hit++;
+
+ ret = 1;
+ /* s->server=0; */
+ s->handshake_func = dtls1_connect;
+ s->ctx->stats.sess_connect_good++;
+
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+
+ /* done with handshaking */
+ s->d1->handshake_read_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ goto end;
+ /* break; */
+
+ default:
+ SSLerr(SSL_F_DTLS1_CONNECT, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ /* break; */
+ }
+
+ /* did we do anything */
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if (s->debug) {
+ if ((ret = BIO_flush(s->wbio)) <= 0)
+ goto end;
+ }
+
+ if ((cb != NULL) && (s->state != state)) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+ end:
+ s->in_handshake--;
+
#ifndef OPENSSL_NO_SCTP
- /* Notify SCTP BIO socket to leave handshake
- * mode and allow stream identifier other
- * than 0. Will be ignored if no SCTP is used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL);
+ /*
+ * Notify SCTP BIO socket to leave handshake mode and allow stream
+ * identifier other than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ s->in_handshake, NULL);
#endif
- if (buf != NULL)
- BUF_MEM_free(buf);
- if (cb != NULL)
- cb(s,SSL_CB_CONNECT_EXIT,ret);
- return(ret);
- }
+ if (buf != NULL)
+ BUF_MEM_free(buf);
+ if (cb != NULL)
+ cb(s, SSL_CB_CONNECT_EXIT, ret);
+ 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) ||
+{
+ 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 ||
+ !sess->session_id_length ||
#else
- (!sess->session_id_length && !sess->tlsext_tick) ||
+ (!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 */
+ (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;
- }
+ /* 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;
+ l = (p - d);
+ d = buf;
- d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l);
+ 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;
+ 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);
- }
+ /* 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);
- }
+ /* 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;
-
- 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);
-
- if (!ok) return((int)n);
-
- if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST)
- {
- s->d1->send_cookie = 0;
- s->s3->tmp.reuse_message=1;
- return(1);
- }
-
- data = (unsigned char *)s->init_msg;
-
- if ((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;
- }
- data+=2;
-
- cookie_len = *(data++);
- if ( cookie_len > sizeof(s->d1->cookie))
- {
- al=SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
- }
-
- memcpy(s->d1->cookie, data, cookie_len);
- s->d1->cookie_len = cookie_len;
-
- s->d1->send_cookie = 1;
- return 1;
-
-f_err:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return -1;
- }
+{
+ int n, al, ok = 0;
+ unsigned char *data;
+ unsigned int cookie_len;
+
+ 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);
+
+ if (!ok)
+ return ((int)n);
+
+ if (s->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ s->d1->send_cookie = 0;
+ s->s3->tmp.reuse_message = 1;
+ return (1);
+ }
+
+ data = (unsigned char *)s->init_msg;
+
+ if ((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;
+ }
+ data += 2;
+
+ cookie_len = *(data++);
+ if (cookie_len > sizeof(s->d1->cookie)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto f_err;
+ }
+
+ memcpy(s->d1->cookie, data, cookie_len);
+ s->d1->cookie_len = cookie_len;
+
+ s->d1->send_cookie = 1;
+ return 1;
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+}
int dtls1_send_client_key_exchange(SSL *s)
- {
- unsigned char *p,*d;
- int n;
- unsigned long alg_k;
+{
+ unsigned char *p, *d;
+ int n;
+ unsigned long alg_k;
#ifndef OPENSSL_NO_RSA
- unsigned char *q;
- EVP_PKEY *pkey=NULL;
+ unsigned char *q;
+ EVP_PKEY *pkey = NULL;
#endif
#ifndef OPENSSL_NO_KRB5
- KSSL_ERR kssl_err;
-#endif /* 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;
+ 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;
+ if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
+ d = (unsigned char *)s->init_buf->data;
+ p = &(d[DTLS1_HM_HEADER_LENGTH]);
- /* Fool emacs indentation */
- if (0) {}
+ 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);
- }
+ 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);
- }
+ 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*/
- }
+ 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_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;
- }
- }
+ 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:
+ 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);
+ 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);
- }
+ 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;
+{
+ unsigned char *p, *d;
+ unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
+ EVP_PKEY *pkey;
#ifndef OPENSSL_NO_RSA
- unsigned u=0;
+ unsigned u = 0;
#endif
- unsigned long n;
+ unsigned long n;
#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
- int j;
+ 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;
+ 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]));
+ 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
+ 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
+ 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
+ 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;
- }
+ {
+ 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) ;
+ 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;
+ 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);
+ /* 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;
+ }
- /* s->state = SSL3_ST_CW_CERT_VRFY_B */
- return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
-err:
- return(-1);
- }
+ /* 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));
- }
+{
+ 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
index 3da2b4c8c2a7..e876364f2c89 100644
--- a/ssl/d1_enc.c
+++ b/ssl/d1_enc.c
@@ -1,7 +1,7 @@
/* ssl/d1_enc.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,21 +62,21 @@
* 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:
@@ -91,10 +91,10 @@
* 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
+ * 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
@@ -106,7 +106,7 @@
* 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
@@ -116,146 +116,136 @@
#include <stdio.h>
#include "ssl_locl.h"
#ifndef OPENSSL_NO_COMP
-#include <openssl/comp.h>
+# 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>
+# include <openssl/des.h>
#endif
-/* dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
+/*-
+ * 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. */
+ * 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;
+{
+ 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);
- }
+ 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);
+ printf("dtls1_enc(%d)\n", send);
+#endif /* KSSL_DEBUG */
- if ((bs != 1) && send)
- {
- i=bs-((int)l%bs);
+ 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);
- /* Add weird padding of upto 256 bytes */
+ if ((bs != 1) && send) {
+ i = bs - ((int)l % bs);
- /* 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;
- }
+ /* 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 */
+ {
+ 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;
+ if (!send) {
+ if (l == 0 || l % bs != 0)
+ return 0;
+ }
-#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 (EVP_Cipher(ds, rec->data, rec->input, l) < 1)
+ return -1;
- if ((bs != 1) && !send)
- return tls1_cbc_remove_padding(s, rec, bs, mac_size);
- }
- 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 14337b31a4e9..94acb15de638 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -1,7 +1,7 @@
/* ssl/d1_lib.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,245 +63,244 @@
#include "ssl_locl.h"
#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
-#include <sys/timeb.h>
+# include <sys/timeb.h>
#endif
static void get_current_time(struct timeval *t);
-const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
+const char dtls1_version_str[] = "DTLSv1" OPENSSL_VERSION_PTEXT;
int dtls1_listen(SSL *s, struct sockaddr *client);
-SSL3_ENC_METHOD DTLSv1_enc_data={
+SSL3_ENC_METHOD DTLSv1_enc_data = {
dtls1_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,
- };
+ 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,
+};
long dtls1_default_timeout(void)
- {
- /* 2 hours, the 24 hours mentioned in the DTLSv1 spec
- * is way too long for http, the cache would over fill */
- return(60*60*2);
- }
+{
+ /*
+ * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
+ * http, the cache would over fill
+ */
+ return (60 * 60 * 2);
+}
int dtls1_new(SSL *s)
- {
- DTLS1_STATE *d1;
-
- if (!ssl3_new(s)) return(0);
- if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0);
- memset(d1,0, sizeof *d1);
-
- /* d1->handshake_epoch=0; */
-
- d1->unprocessed_rcds.q=pqueue_new();
- d1->processed_rcds.q=pqueue_new();
- d1->buffered_messages = pqueue_new();
- d1->sent_messages=pqueue_new();
- d1->buffered_app_data.q=pqueue_new();
-
- if ( s->server)
- {
- d1->cookie_len = sizeof(s->d1->cookie);
- }
-
- d1->link_mtu = 0;
- d1->mtu = 0;
-
- if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q
- || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
- {
- if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
- if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
- if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
- if ( d1->sent_messages) pqueue_free(d1->sent_messages);
- if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
- OPENSSL_free(d1);
- return (0);
- }
-
- s->d1=d1;
- s->method->ssl_clear(s);
- return(1);
- }
+{
+ DTLS1_STATE *d1;
+
+ if (!ssl3_new(s))
+ return (0);
+ if ((d1 = OPENSSL_malloc(sizeof *d1)) == NULL)
+ return (0);
+ memset(d1, 0, sizeof *d1);
+
+ /* d1->handshake_epoch=0; */
+
+ d1->unprocessed_rcds.q = pqueue_new();
+ d1->processed_rcds.q = pqueue_new();
+ d1->buffered_messages = pqueue_new();
+ d1->sent_messages = pqueue_new();
+ d1->buffered_app_data.q = pqueue_new();
+
+ if (s->server) {
+ d1->cookie_len = sizeof(s->d1->cookie);
+ }
+
+ d1->link_mtu = 0;
+ d1->mtu = 0;
+
+ if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q
+ || !d1->buffered_messages || !d1->sent_messages
+ || !d1->buffered_app_data.q) {
+ if (d1->unprocessed_rcds.q)
+ pqueue_free(d1->unprocessed_rcds.q);
+ if (d1->processed_rcds.q)
+ pqueue_free(d1->processed_rcds.q);
+ if (d1->buffered_messages)
+ pqueue_free(d1->buffered_messages);
+ if (d1->sent_messages)
+ pqueue_free(d1->sent_messages);
+ if (d1->buffered_app_data.q)
+ pqueue_free(d1->buffered_app_data.q);
+ OPENSSL_free(d1);
+ return (0);
+ }
+
+ s->d1 = d1;
+ s->method->ssl_clear(s);
+ return (1);
+}
static void dtls1_clear_queues(SSL *s)
- {
+{
pitem *item = NULL;
hm_fragment *frag = NULL;
- DTLS1_RECORD_DATA *rdata;
-
- while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
- {
- rdata = (DTLS1_RECORD_DATA *) item->data;
- if (rdata->rbuf.buf)
- {
- OPENSSL_free(rdata->rbuf.buf);
- }
+ DTLS1_RECORD_DATA *rdata;
+
+ while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
OPENSSL_free(item->data);
pitem_free(item);
- }
+ }
- while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
- {
- rdata = (DTLS1_RECORD_DATA *) item->data;
- if (rdata->rbuf.buf)
- {
- OPENSSL_free(rdata->rbuf.buf);
- }
+ while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
OPENSSL_free(item->data);
pitem_free(item);
- }
+ }
- while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
- {
+ while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
- }
+ }
- while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
- {
+ while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
- }
+ }
- while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
- {
- rdata = (DTLS1_RECORD_DATA *) item->data;
- if (rdata->rbuf.buf)
- {
- OPENSSL_free(rdata->rbuf.buf);
- }
- OPENSSL_free(item->data);
- pitem_free(item);
- }
- }
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+}
void dtls1_free(SSL *s)
- {
- ssl3_free(s);
+{
+ ssl3_free(s);
- dtls1_clear_queues(s);
+ dtls1_clear_queues(s);
pqueue_free(s->d1->unprocessed_rcds.q);
pqueue_free(s->d1->processed_rcds.q);
pqueue_free(s->d1->buffered_messages);
- pqueue_free(s->d1->sent_messages);
- pqueue_free(s->d1->buffered_app_data.q);
+ pqueue_free(s->d1->sent_messages);
+ pqueue_free(s->d1->buffered_app_data.q);
- OPENSSL_free(s->d1);
- s->d1 = NULL;
- }
+ OPENSSL_free(s->d1);
+ s->d1 = NULL;
+}
void dtls1_clear(SSL *s)
- {
+{
pqueue unprocessed_rcds;
pqueue processed_rcds;
pqueue buffered_messages;
- pqueue sent_messages;
- pqueue buffered_app_data;
- unsigned int mtu;
- unsigned int link_mtu;
-
- if (s->d1)
- {
- unprocessed_rcds = s->d1->unprocessed_rcds.q;
- processed_rcds = s->d1->processed_rcds.q;
- buffered_messages = s->d1->buffered_messages;
- sent_messages = s->d1->sent_messages;
- buffered_app_data = s->d1->buffered_app_data.q;
- mtu = s->d1->mtu;
- link_mtu = s->d1->link_mtu;
-
- dtls1_clear_queues(s);
-
- memset(s->d1, 0, sizeof(*(s->d1)));
-
- if (s->server)
- {
- s->d1->cookie_len = sizeof(s->d1->cookie);
- }
-
- if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)
- {
- s->d1->mtu = mtu;
- s->d1->link_mtu = link_mtu;
- }
-
- s->d1->unprocessed_rcds.q = unprocessed_rcds;
- s->d1->processed_rcds.q = processed_rcds;
- s->d1->buffered_messages = buffered_messages;
- s->d1->sent_messages = sent_messages;
- s->d1->buffered_app_data.q = buffered_app_data;
- }
-
- ssl3_clear(s);
- if (s->options & SSL_OP_CISCO_ANYCONNECT)
- s->version=DTLS1_BAD_VER;
- else
- s->version=DTLS1_VERSION;
- }
+ pqueue sent_messages;
+ pqueue buffered_app_data;
+ unsigned int mtu;
+ unsigned int link_mtu;
+
+ if (s->d1) {
+ unprocessed_rcds = s->d1->unprocessed_rcds.q;
+ processed_rcds = s->d1->processed_rcds.q;
+ buffered_messages = s->d1->buffered_messages;
+ sent_messages = s->d1->sent_messages;
+ buffered_app_data = s->d1->buffered_app_data.q;
+ mtu = s->d1->mtu;
+ link_mtu = s->d1->link_mtu;
+
+ dtls1_clear_queues(s);
+
+ memset(s->d1, 0, sizeof(*(s->d1)));
+
+ if (s->server) {
+ s->d1->cookie_len = sizeof(s->d1->cookie);
+ }
+
+ if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
+ s->d1->mtu = mtu;
+ s->d1->link_mtu = link_mtu;
+ }
+
+ s->d1->unprocessed_rcds.q = unprocessed_rcds;
+ s->d1->processed_rcds.q = processed_rcds;
+ s->d1->buffered_messages = buffered_messages;
+ s->d1->sent_messages = sent_messages;
+ s->d1->buffered_app_data.q = buffered_app_data;
+ }
+
+ ssl3_clear(s);
+ if (s->options & SSL_OP_CISCO_ANYCONNECT)
+ s->version = DTLS1_BAD_VER;
+ else
+ s->version = DTLS1_VERSION;
+}
long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
- {
- int ret=0;
-
- switch (cmd)
- {
- case DTLS_CTRL_GET_TIMEOUT:
- if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
- {
- ret = 1;
- }
- break;
- case DTLS_CTRL_HANDLE_TIMEOUT:
- ret = dtls1_handle_timeout(s);
- break;
- case DTLS_CTRL_LISTEN:
- ret = dtls1_listen(s, parg);
- break;
- case SSL_CTRL_CHECK_PROTO_VERSION:
- /* For library-internal use; checks that the current protocol
- * is the highest enabled version (according to s->ctx->method,
- * as version negotiation may have changed s->method). */
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case DTLS_CTRL_GET_TIMEOUT:
+ if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
+ ret = 1;
+ }
+ break;
+ case DTLS_CTRL_HANDLE_TIMEOUT:
+ ret = dtls1_handle_timeout(s);
+ break;
+ case DTLS_CTRL_LISTEN:
+ ret = dtls1_listen(s, parg);
+ break;
+ case SSL_CTRL_CHECK_PROTO_VERSION:
+ /*
+ * For library-internal use; checks that the current protocol is the
+ * 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.
+# error Code needs update for DTLS_method() support beyond DTLS1_VERSION.
#endif
- /* Just one protocol version is supported so far;
- * fail closed if the version is not as expected. */
- return s->version == DTLS_MAX_VERSION;
- case DTLS_CTRL_SET_LINK_MTU:
- if (larg < (long)dtls1_link_min_mtu())
- return 0;
- s->d1->link_mtu = larg;
- return 1;
- case DTLS_CTRL_GET_LINK_MIN_MTU:
- return (long)dtls1_link_min_mtu();
- case SSL_CTRL_SET_MTU:
- /*
- * We may not have a BIO set yet so can't call dtls1_min_mtu()
- * We'll have to make do with dtls1_link_min_mtu() and max overhead
- */
- if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
- return 0;
- s->d1->mtu = larg;
- return larg;
- default:
- ret = ssl3_ctrl(s, cmd, larg, parg);
- break;
- }
- return(ret);
- }
+ /*
+ * Just one protocol version is supported so far; fail closed if the
+ * version is not as expected.
+ */
+ return s->version == DTLS_MAX_VERSION;
+ case DTLS_CTRL_SET_LINK_MTU:
+ if (larg < (long)dtls1_link_min_mtu())
+ return 0;
+ s->d1->link_mtu = larg;
+ return 1;
+ case DTLS_CTRL_GET_LINK_MIN_MTU:
+ return (long)dtls1_link_min_mtu();
+ case SSL_CTRL_SET_MTU:
+ /*
+ * We may not have a BIO set yet so can't call dtls1_min_mtu()
+ * We'll have to make do with dtls1_link_min_mtu() and max overhead
+ */
+ if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
+ return 0;
+ s->d1->mtu = larg;
+ return larg;
+ default:
+ ret = ssl3_ctrl(s, cmd, larg, parg);
+ break;
+ }
+ return (ret);
+}
/*
* As it's impossible to use stream ciphers in "datagram" mode, this
@@ -311,210 +310,199 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
* available, but if new ones emerge, they will have to be added...
*/
const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
- {
- const SSL_CIPHER *ciph = ssl3_get_cipher(u);
+{
+ const SSL_CIPHER *ciph = ssl3_get_cipher(u);
- if (ciph != NULL)
- {
- if (ciph->algorithm_enc == SSL_RC4)
- return NULL;
- }
+ if (ciph != NULL) {
+ if (ciph->algorithm_enc == SSL_RC4)
+ return NULL;
+ }
- return ciph;
- }
+ return ciph;
+}
void dtls1_start_timer(SSL *s)
- {
+{
#ifndef OPENSSL_NO_SCTP
- /* Disable timer for SCTP */
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
- return;
- }
+ /* Disable timer for SCTP */
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+ return;
+ }
#endif
- /* If timer is not set, initialize duration with 1 second */
- if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
- {
- s->d1->timeout_duration = 1;
- }
-
- /* Set timeout to current time */
- get_current_time(&(s->d1->next_timeout));
-
- /* Add duration to current time */
- s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
- }
-
-struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
- {
- struct timeval timenow;
-
- /* If no timeout is set, just return NULL */
- if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
- {
- return NULL;
- }
-
- /* Get current time */
- get_current_time(&timenow);
-
- /* If timer already expired, set remaining time to 0 */
- if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
- (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
- s->d1->next_timeout.tv_usec <= timenow.tv_usec))
- {
- memset(timeleft, 0, sizeof(struct timeval));
- return timeleft;
- }
-
- /* Calculate time left until timer expires */
- memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
- timeleft->tv_sec -= timenow.tv_sec;
- timeleft->tv_usec -= timenow.tv_usec;
- if (timeleft->tv_usec < 0)
- {
- timeleft->tv_sec--;
- timeleft->tv_usec += 1000000;
- }
-
- /* If remaining time is less than 15 ms, set it to 0
- * to prevent issues because of small devergences with
- * socket timeouts.
- */
- if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
- {
- memset(timeleft, 0, sizeof(struct timeval));
- }
-
-
- return timeleft;
- }
+ /* If timer is not set, initialize duration with 1 second */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
+ s->d1->timeout_duration = 1;
+ }
+
+ /* Set timeout to current time */
+ get_current_time(&(s->d1->next_timeout));
+
+ /* Add duration to current time */
+ s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ &(s->d1->next_timeout));
+}
+
+struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
+{
+ struct timeval timenow;
+
+ /* If no timeout is set, just return NULL */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
+ return NULL;
+ }
+
+ /* Get current time */
+ get_current_time(&timenow);
+
+ /* If timer already expired, set remaining time to 0 */
+ if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
+ (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
+ s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
+ memset(timeleft, 0, sizeof(struct timeval));
+ return timeleft;
+ }
+
+ /* Calculate time left until timer expires */
+ memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
+ timeleft->tv_sec -= timenow.tv_sec;
+ timeleft->tv_usec -= timenow.tv_usec;
+ if (timeleft->tv_usec < 0) {
+ timeleft->tv_sec--;
+ timeleft->tv_usec += 1000000;
+ }
+
+ /*
+ * If remaining time is less than 15 ms, set it to 0 to prevent issues
+ * because of small devergences with socket timeouts.
+ */
+ if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
+ memset(timeleft, 0, sizeof(struct timeval));
+ }
+
+ return timeleft;
+}
int dtls1_is_timer_expired(SSL *s)
- {
- struct timeval timeleft;
+{
+ struct timeval timeleft;
- /* Get time left until timeout, return false if no timer running */
- if (dtls1_get_timeout(s, &timeleft) == NULL)
- {
- return 0;
- }
+ /* Get time left until timeout, return false if no timer running */
+ if (dtls1_get_timeout(s, &timeleft) == NULL) {
+ return 0;
+ }
- /* Return false if timer is not expired yet */
- if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
- {
- return 0;
- }
+ /* Return false if timer is not expired yet */
+ if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
+ return 0;
+ }
- /* Timer expired, so return true */
- return 1;
- }
+ /* Timer expired, so return true */
+ return 1;
+}
void dtls1_double_timeout(SSL *s)
- {
- s->d1->timeout_duration *= 2;
- if (s->d1->timeout_duration > 60)
- s->d1->timeout_duration = 60;
- dtls1_start_timer(s);
- }
+{
+ s->d1->timeout_duration *= 2;
+ if (s->d1->timeout_duration > 60)
+ s->d1->timeout_duration = 60;
+ dtls1_start_timer(s);
+}
void dtls1_stop_timer(SSL *s)
- {
- /* Reset everything */
- memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
- memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
- s->d1->timeout_duration = 1;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
- /* Clear retransmission buffer */
- dtls1_clear_record_buffer(s);
- }
+{
+ /* Reset everything */
+ memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
+ memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+ s->d1->timeout_duration = 1;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
+ &(s->d1->next_timeout));
+ /* Clear retransmission buffer */
+ dtls1_clear_record_buffer(s);
+}
int dtls1_check_timeout_num(SSL *s)
- {
- unsigned int mtu;
-
- s->d1->timeout.num_alerts++;
-
- /* Reduce MTU after 2 unsuccessful retransmissions */
- if (s->d1->timeout.num_alerts > 2
- && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
- {
- mtu = BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
- if(mtu < s->d1->mtu)
- s->d1->mtu = mtu;
- }
-
- if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
- {
- /* fail the connection, enough alerts have been sent */
- SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM,SSL_R_READ_TIMEOUT_EXPIRED);
- return -1;
- }
-
- return 0;
- }
+{
+ unsigned int mtu;
+
+ s->d1->timeout.num_alerts++;
+
+ /* Reduce MTU after 2 unsuccessful retransmissions */
+ if (s->d1->timeout.num_alerts > 2
+ && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ mtu =
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
+ NULL);
+ if (mtu < s->d1->mtu)
+ s->d1->mtu = mtu;
+ }
+
+ if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
+ /* fail the connection, enough alerts have been sent */
+ SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED);
+ return -1;
+ }
+
+ return 0;
+}
int dtls1_handle_timeout(SSL *s)
- {
- /* if no timer is expired, don't do anything */
- if (!dtls1_is_timer_expired(s))
- {
- return 0;
- }
-
- dtls1_double_timeout(s);
+{
+ /* if no timer is expired, don't do anything */
+ if (!dtls1_is_timer_expired(s)) {
+ return 0;
+ }
- if (dtls1_check_timeout_num(s) < 0)
- return -1;
+ dtls1_double_timeout(s);
- s->d1->timeout.read_timeouts++;
- if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
- {
- s->d1->timeout.read_timeouts = 1;
- }
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+ s->d1->timeout.read_timeouts++;
+ if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
+ s->d1->timeout.read_timeouts = 1;
+ }
#ifndef OPENSSL_NO_HEARTBEATS
- if (s->tlsext_hb_pending)
- {
- s->tlsext_hb_pending = 0;
- return dtls1_heartbeat(s);
- }
+ if (s->tlsext_hb_pending) {
+ s->tlsext_hb_pending = 0;
+ return dtls1_heartbeat(s);
+ }
#endif
- dtls1_start_timer(s);
- return dtls1_retransmit_buffered_messages(s);
- }
+ dtls1_start_timer(s);
+ return dtls1_retransmit_buffered_messages(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;
+ struct _timeb tb;
+ _ftime(&tb);
+ t->tv_sec = (long)tb.time;
+ t->tv_usec = (long)tb.millitm * 1000;
#elif defined(OPENSSL_SYS_VMS)
- struct timeb tb;
- ftime(&tb);
- t->tv_sec = (long)tb.time;
- t->tv_usec = (long)tb.millitm * 1000;
+ struct timeb tb;
+ ftime(&tb);
+ t->tv_sec = (long)tb.time;
+ t->tv_usec = (long)tb.millitm * 1000;
#else
- gettimeofday(t, NULL);
+ gettimeofday(t, NULL);
#endif
}
int dtls1_listen(SSL *s, struct sockaddr *client)
- {
- int ret;
-
- SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
- s->d1->listen = 1;
-
- ret = SSL_accept(s);
- if (ret <= 0) return ret;
-
- (void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
- return 1;
- }
+{
+ int ret;
+
+ SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
+ s->d1->listen = 1;
+
+ ret = SSL_accept(s);
+ if (ret <= 0)
+ return ret;
+
+ (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
+ return 1;
+}
diff --git a/ssl/d1_meth.c b/ssl/d1_meth.c
index 5c4004bfe3c7..aaa718c92718 100644
--- a/ssl/d1_meth.c
+++ b/ssl/d1_meth.c
@@ -1,7 +1,7 @@
/* ssl/d1_meth.h */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -63,15 +63,12 @@
static const SSL_METHOD *dtls1_get_method(int ver);
static const SSL_METHOD *dtls1_get_method(int ver)
- {
- if (ver == DTLS1_VERSION)
- return(DTLSv1_method());
- else
- return(NULL);
- }
+{
+ if (ver == DTLS1_VERSION)
+ return (DTLSv1_method());
+ else
+ return (NULL);
+}
IMPLEMENT_dtls1_meth_func(DTLSv1_method,
- dtls1_accept,
- dtls1_connect,
- dtls1_get_method)
-
+ dtls1_accept, dtls1_connect, dtls1_get_method)
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 0059fe2f152d..7b49a7dd7a6d 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -1,7 +1,7 @@
/* ssl/d1_pkt.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,21 +62,21 @@
* 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:
@@ -91,10 +91,10 @@
* 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
+ * 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
@@ -106,7 +106,7 @@
* 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
@@ -123,610 +123,621 @@
#include <openssl/rand.h>
/* mod 128 saturating subtract of two 64-bit values in big-endian order */
-static int satsub64be(const unsigned char *v1,const unsigned char *v2)
-{ int ret,sat,brw,i;
-
- if (sizeof(long) == 8) do
- { const union { long one; char little; } is_endian = {1};
- long l;
-
- if (is_endian.little) break;
- /* not reached on little-endians */
- /* following test is redundant, because input is
- * always aligned, but I take no chances... */
- if (((size_t)v1|(size_t)v2)&0x7) break;
-
- l = *((long *)v1);
- l -= *((long *)v2);
- if (l>128) return 128;
- else if (l<-128) return -128;
- else return (int)l;
- } while (0);
-
- ret = (int)v1[7]-(int)v2[7];
- sat = 0;
- brw = ret>>8; /* brw is either 0 or -1 */
- if (ret & 0x80)
- { for (i=6;i>=0;i--)
- { brw += (int)v1[i]-(int)v2[i];
- sat |= ~brw;
- brw >>= 8;
- }
- }
- else
- { for (i=6;i>=0;i--)
- { brw += (int)v1[i]-(int)v2[i];
- sat |= brw;
- brw >>= 8;
- }
- }
- brw <<= 8; /* brw is either 0 or -256 */
-
- if (sat&0xff) return brw | 0x80;
- else return brw + (ret&0xFF);
+static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+{
+ int ret, sat, brw, i;
+
+ if (sizeof(long) == 8)
+ do {
+ const union {
+ long one;
+ char little;
+ } is_endian = {
+ 1
+ };
+ long l;
+
+ if (is_endian.little)
+ break;
+ /* not reached on little-endians */
+ /*
+ * following test is redundant, because input is always aligned,
+ * but I take no chances...
+ */
+ if (((size_t)v1 | (size_t)v2) & 0x7)
+ break;
+
+ l = *((long *)v1);
+ l -= *((long *)v2);
+ if (l > 128)
+ return 128;
+ else if (l < -128)
+ return -128;
+ else
+ return (int)l;
+ } while (0);
+
+ ret = (int)v1[7] - (int)v2[7];
+ sat = 0;
+ brw = ret >> 8; /* brw is either 0 or -1 */
+ if (ret & 0x80) {
+ for (i = 6; i >= 0; i--) {
+ brw += (int)v1[i] - (int)v2[i];
+ sat |= ~brw;
+ brw >>= 8;
+ }
+ } else {
+ for (i = 6; i >= 0; i--) {
+ brw += (int)v1[i] - (int)v2[i];
+ sat |= brw;
+ brw >>= 8;
+ }
+ }
+ brw <<= 8; /* brw is either 0 or -256 */
+
+ if (sat & 0xff)
+ return brw | 0x80;
+ else
+ return brw + (ret & 0xFF);
}
-static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
- int len, int peek);
+static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
+ int len, int peek);
static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap);
static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap);
-static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
- unsigned int *is_next_epoch);
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch);
#if 0
static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
- unsigned short *priority, unsigned long *offset);
+ unsigned short *priority,
+ unsigned long *offset);
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
- unsigned char *priority);
+ unsigned char *priority);
static int dtls1_process_record(SSL *s);
/* copy buffered record into SSL structure */
-static int
-dtls1_copy_record(SSL *s, pitem *item)
- {
+static int dtls1_copy_record(SSL *s, pitem *item)
+{
DTLS1_RECORD_DATA *rdata;
rdata = (DTLS1_RECORD_DATA *)item->data;
-
+
if (s->s3->rbuf.buf != NULL)
OPENSSL_free(s->s3->rbuf.buf);
-
+
s->packet = rdata->packet;
s->packet_length = rdata->packet_length;
memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
-
- /* Set proper sequence number for mac calculation */
- memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
-
- return(1);
- }
+ /* Set proper sequence number for mac calculation */
+ memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
+
+ return (1);
+}
static int
dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
- {
- DTLS1_RECORD_DATA *rdata;
- pitem *item;
-
- /* Limit the size of the queue to prevent DOS attacks */
- if (pqueue_size(queue->q) >= 100)
- return 0;
-
- rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
- item = pitem_new(priority, rdata);
- if (rdata == NULL || item == NULL)
- {
- if (rdata != NULL) OPENSSL_free(rdata);
- if (item != NULL) pitem_free(item);
-
- SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
- return(0);
- }
-
- rdata->packet = s->packet;
- rdata->packet_length = s->packet_length;
- memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
- memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
-
- item->data = rdata;
+{
+ DTLS1_RECORD_DATA *rdata;
+ pitem *item;
+
+ /* Limit the size of the queue to prevent DOS attacks */
+ if (pqueue_size(queue->q) >= 100)
+ return 0;
+
+ rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA));
+ item = pitem_new(priority, rdata);
+ if (rdata == NULL || item == NULL) {
+ if (rdata != NULL)
+ OPENSSL_free(rdata);
+ if (item != NULL)
+ pitem_free(item);
+
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ rdata->packet = s->packet;
+ rdata->packet_length = s->packet_length;
+ memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD));
+
+ item->data = rdata;
#ifndef OPENSSL_NO_SCTP
- /* Store bio_dgram_sctp_rcvinfo struct */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- (s->state == SSL3_ST_SR_FINISHED_A || s->state == SSL3_ST_CR_FINISHED_A)) {
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
- }
+ /* Store bio_dgram_sctp_rcvinfo struct */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ (s->state == SSL3_ST_SR_FINISHED_A
+ || s->state == SSL3_ST_CR_FINISHED_A)) {
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO,
+ sizeof(rdata->recordinfo), &rdata->recordinfo);
+ }
#endif
- s->packet = NULL;
- s->packet_length = 0;
- memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
- memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
-
- if (!ssl3_setup_buffers(s))
- {
- SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
- if (rdata->rbuf.buf != NULL)
- OPENSSL_free(rdata->rbuf.buf);
- OPENSSL_free(rdata);
- pitem_free(item);
- return(-1);
- }
-
- /* insert should not fail, since duplicates are dropped */
- if (pqueue_insert(queue->q, item) == NULL)
- {
- SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
- if (rdata->rbuf.buf != NULL)
- OPENSSL_free(rdata->rbuf.buf);
- OPENSSL_free(rdata);
- pitem_free(item);
- return(-1);
- }
-
- return(1);
- }
+ s->packet = NULL;
+ s->packet_length = 0;
+ memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
+ memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
+
+ if (!ssl3_setup_buffers(s)) {
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ if (rdata->rbuf.buf != NULL)
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return (-1);
+ }
+ /* insert should not fail, since duplicates are dropped */
+ if (pqueue_insert(queue->q, item) == NULL) {
+ SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+ if (rdata->rbuf.buf != NULL)
+ OPENSSL_free(rdata->rbuf.buf);
+ OPENSSL_free(rdata);
+ pitem_free(item);
+ return (-1);
+ }
-static int
-dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
- {
+ return (1);
+}
+
+static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
+{
pitem *item;
item = pqueue_pop(queue->q);
- if (item)
- {
+ if (item) {
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
- pitem_free(item);
-
- return(1);
- }
+ pitem_free(item);
- return(0);
+ return (1);
}
+ return (0);
+}
-/* retrieve a buffered record that belongs to the new epoch, i.e., not processed
- * yet */
+/*
+ * retrieve a buffered record that belongs to the new epoch, i.e., not
+ * processed yet
+ */
#define dtls1_get_unprocessed_record(s) \
dtls1_retrieve_buffered_record((s), \
&((s)->d1->unprocessed_rcds))
-/* retrieve a buffered record that belongs to the current epoch, ie, processed */
+/*
+ * retrieve a buffered record that belongs to the current epoch, ie,
+ * processed
+ */
#define dtls1_get_processed_record(s) \
dtls1_retrieve_buffered_record((s), \
&((s)->d1->processed_rcds))
-static int
-dtls1_process_buffered_records(SSL *s)
- {
+static int dtls1_process_buffered_records(SSL *s)
+{
pitem *item;
-
+
item = pqueue_peek(s->d1->unprocessed_rcds.q);
- if (item)
- {
+ if (item) {
/* Check if epoch is current. */
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
- return(1); /* Nothing to do. */
-
+ return (1); /* Nothing to do. */
+
/* Process all the records. */
- while (pqueue_peek(s->d1->unprocessed_rcds.q))
- {
+ while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
- if ( ! dtls1_process_record(s))
- return(0);
- if(dtls1_buffer_record(s, &(s->d1->processed_rcds),
- s->s3->rrec.seq_num)<0)
+ if (!dtls1_process_record(s))
+ return (0);
+ if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
+ s->s3->rrec.seq_num) < 0)
return -1;
- }
}
+ }
- /* sync epoch numbers once all the unprocessed records
- * have been processed */
+ /*
+ * sync epoch numbers once all the unprocessed records have been
+ * processed
+ */
s->d1->processed_rcds.epoch = s->d1->r_epoch;
s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
- return(1);
- }
-
+ return (1);
+}
#if 0
-static int
-dtls1_get_buffered_record(SSL *s)
- {
- pitem *item;
- PQ_64BIT priority =
- (((PQ_64BIT)s->d1->handshake_read_seq) << 32) |
- ((PQ_64BIT)s->d1->r_msg_hdr.frag_off);
-
- if ( ! SSL_in_init(s)) /* if we're not (re)negotiating,
- nothing buffered */
- return 0;
-
-
- item = pqueue_peek(s->d1->rcvd_records);
- if (item && item->priority == priority)
- {
- /* Check if we've received the record of interest. It must be
- * a handshake record, since data records as passed up without
- * buffering */
- DTLS1_RECORD_DATA *rdata;
- item = pqueue_pop(s->d1->rcvd_records);
- rdata = (DTLS1_RECORD_DATA *)item->data;
-
- if (s->s3->rbuf.buf != NULL)
- OPENSSL_free(s->s3->rbuf.buf);
-
- s->packet = rdata->packet;
- s->packet_length = rdata->packet_length;
- memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
- memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
-
- OPENSSL_free(item->data);
- pitem_free(item);
-
- /* s->d1->next_expected_seq_num++; */
- return(1);
- }
-
- return 0;
- }
+static int dtls1_get_buffered_record(SSL *s)
+{
+ pitem *item;
+ PQ_64BIT priority =
+ (((PQ_64BIT) s->d1->handshake_read_seq) << 32) |
+ ((PQ_64BIT) s->d1->r_msg_hdr.frag_off);
+
+ /* if we're not (re)negotiating, nothing buffered */
+ if (!SSL_in_init(s))
+ return 0;
+
+ item = pqueue_peek(s->d1->rcvd_records);
+ if (item && item->priority == priority) {
+ /*
+ * Check if we've received the record of interest. It must be a
+ * handshake record, since data records as passed up without
+ * buffering
+ */
+ DTLS1_RECORD_DATA *rdata;
+ item = pqueue_pop(s->d1->rcvd_records);
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+
+ if (s->s3->rbuf.buf != NULL)
+ OPENSSL_free(s->s3->rbuf.buf);
+
+ s->packet = rdata->packet;
+ s->packet_length = rdata->packet_length;
+ memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER));
+ memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD));
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+
+ /* s->d1->next_expected_seq_num++; */
+ return (1);
+ }
+
+ return 0;
+}
#endif
-static int
-dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s)
{
- int i,al;
- int enc_err;
- SSL_SESSION *sess;
- SSL3_RECORD *rr;
- unsigned int mac_size, orig_len;
- unsigned char md[EVP_MAX_MD_SIZE];
-
- rr= &(s->s3->rrec);
- sess = s->session;
-
- /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
- * and we have that many bytes in s->packet
- */
- rr->input= &(s->packet[DTLS1_RT_HEADER_LENGTH]);
-
- /* ok, we can now read from 's->packet' data into 'rr'
- * rr->input points at rr->length bytes, which
- * need to be copied into rr->data by either
- * the decryption or by the decompression
- * When the data is 'copied' into the rr->data buffer,
- * rr->input will be pointed at the new buffer */
-
- /* We now have - encrypted [ MAC [ compressed [ plain ] ] ]
- * rr->length bytes of encrypted compressed stuff. */
-
- /* check is not needed I believe */
- if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
- {
- al=SSL_AD_RECORD_OVERFLOW;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
- goto f_err;
- }
-
- /* decrypt in place in 'rr->input' */
- rr->data=rr->input;
-
- enc_err = s->method->ssl3_enc->enc(s,0);
- /* enc_err is:
- * 0: (in non-constant time) if the record is publically invalid.
- * 1: if the padding is valid
- * -1: if the padding is invalid */
- if (enc_err == 0)
- {
- /* For DTLS we simply ignore bad packets. */
- rr->length = 0;
- s->packet_length = 0;
- goto err;
- }
+ int i, al;
+ int enc_err;
+ SSL_SESSION *sess;
+ SSL3_RECORD *rr;
+ unsigned int mac_size, orig_len;
+ unsigned char md[EVP_MAX_MD_SIZE];
+
+ rr = &(s->s3->rrec);
+ sess = s->session;
+
+ /*
+ * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
+ * and we have that many bytes in s->packet
+ */
+ rr->input = &(s->packet[DTLS1_RT_HEADER_LENGTH]);
+
+ /*
+ * ok, we can now read from 's->packet' data into 'rr' rr->input points
+ * at rr->length bytes, which need to be copied into rr->data by either
+ * the decryption or by the decompression When the data is 'copied' into
+ * the rr->data buffer, rr->input will be pointed at the new buffer
+ */
+
+ /*
+ * We now have - encrypted [ MAC [ compressed [ plain ] ] ] rr->length
+ * bytes of encrypted compressed stuff.
+ */
+
+ /* check is not needed I believe */
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ /* decrypt in place in 'rr->input' */
+ rr->data = rr->input;
+
+ enc_err = s->method->ssl3_enc->enc(s, 0);
+ /*-
+ * enc_err is:
+ * 0: (in non-constant time) if the record is publically invalid.
+ * 1: if the padding is valid
+ * -1: if the padding is invalid
+ */
+ if (enc_err == 0) {
+ /* For DTLS we simply ignore bad packets. */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto err;
+ }
#ifdef TLS_DEBUG
-printf("dec %d\n",rr->length);
-{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); }
-printf("\n");
+ printf("dec %d\n", rr->length);
+ {
+ unsigned int z;
+ for (z = 0; z < rr->length; z++)
+ printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+ printf("\n");
#endif
- /* r->length is now the compressed data plus mac */
- if ((sess != NULL) &&
- (s->enc_read_ctx != NULL) &&
- (EVP_MD_CTX_md(s->read_hash) != NULL))
- {
- /* s->read_hash != NULL => mac_size != -1 */
- unsigned char *mac = NULL;
- unsigned char mac_tmp[EVP_MAX_MD_SIZE];
- mac_size=EVP_MD_CTX_size(s->read_hash);
- OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
-
- /* kludge: *_cbc_remove_padding passes padding length in rr->type */
- orig_len = rr->length+((unsigned int)rr->type>>8);
-
- /* orig_len is the length of the record before any padding was
- * removed. This is public information, as is the MAC in use,
- * therefore we can safely process the record in a different
- * amount of time if it's too short to possibly contain a MAC.
- */
- if (orig_len < mac_size ||
- /* CBC records must have a padding length byte too. */
- (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- orig_len < mac_size+1))
- {
- al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT);
- goto f_err;
- }
-
- if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE)
- {
- /* We update the length so that the TLS header bytes
- * can be constructed correctly but we need to extract
- * the MAC in constant time from within the record,
- * without leaking the contents of the padding bytes.
- * */
- mac = mac_tmp;
- ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
- rr->length -= mac_size;
- }
- else
- {
- /* In this case there's no padding, so |orig_len|
- * equals |rec->length| and we checked that there's
- * enough bytes for |mac_size| above. */
- rr->length -= mac_size;
- mac = &rr->data[rr->length];
- }
-
- i=s->method->ssl3_enc->mac(s,md,0 /* not send */);
- if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
- enc_err = -1;
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
- enc_err = -1;
- }
-
- if (enc_err < 0)
- {
- /* decryption failed, silently discard message */
- rr->length = 0;
- s->packet_length = 0;
- goto err;
- }
-
- /* r->length is now just compressed */
- if (s->expand != NULL)
- {
- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH)
- {
- al=SSL_AD_RECORD_OVERFLOW;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- goto f_err;
- }
- if (!ssl3_do_uncompress(s))
- {
- al=SSL_AD_DECOMPRESSION_FAILURE;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_BAD_DECOMPRESSION);
- goto f_err;
- }
- }
-
- if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH)
- {
- al=SSL_AD_RECORD_OVERFLOW;
- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DATA_LENGTH_TOO_LONG);
- goto f_err;
- }
-
- rr->off=0;
- /* So at this point the following is true
- * ssl->s3->rrec.type is the type of record
- * ssl->s3->rrec.length == number of bytes in record
- * ssl->s3->rrec.off == offset to first valid byte
- * ssl->s3->rrec.data == where to take bytes from, increment
- * after use :-).
- */
-
- /* we have pulled in a full packet so zero things */
- s->packet_length=0;
- return(1);
-
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
-err:
- return(0);
-}
+ /* r->length is now the compressed data plus mac */
+ if ((sess != NULL) &&
+ (s->enc_read_ctx != NULL) && (EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ /* s->read_hash != NULL => mac_size != -1 */
+ unsigned char *mac = NULL;
+ unsigned char mac_tmp[EVP_MAX_MD_SIZE];
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
+
+ /*
+ * kludge: *_cbc_remove_padding passes padding length in rr->type
+ */
+ orig_len = rr->length + ((unsigned int)rr->type >> 8);
+
+ /*
+ * orig_len is the length of the record before any padding was
+ * removed. This is public information, as is the MAC in use,
+ * therefore we can safely process the record in a different amount
+ * of time if it's too short to possibly contain a MAC.
+ */
+ if (orig_len < mac_size ||
+ /* CBC records must have a padding length byte too. */
+ (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ orig_len < mac_size + 1)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
+ /*
+ * We update the length so that the TLS header bytes can be
+ * constructed correctly but we need to extract the MAC in
+ * constant time from within the record, without leaking the
+ * contents of the padding bytes.
+ */
+ mac = mac_tmp;
+ ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
+ rr->length -= mac_size;
+ } else {
+ /*
+ * In this case there's no padding, so |orig_len| equals
+ * |rec->length| and we checked that there's enough bytes for
+ * |mac_size| above.
+ */
+ rr->length -= mac_size;
+ mac = &rr->data[rr->length];
+ }
-/* Call this to get a new input record.
+ i = s->method->ssl3_enc->mac(s, md, 0 /* not send */ );
+ if (i < 0 || mac == NULL
+ || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+ enc_err = -1;
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
+ enc_err = -1;
+ }
+
+ if (enc_err < 0) {
+ /* decryption failed, silently discard message */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto err;
+ }
+
+ /* r->length is now just compressed */
+ if (s->expand != NULL) {
+ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD,
+ SSL_R_COMPRESSED_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (!ssl3_do_uncompress(s)) {
+ al = SSL_AD_DECOMPRESSION_FAILURE;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
+ goto f_err;
+ }
+ }
+
+ if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH) {
+ al = SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_DTLS1_PROCESS_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ rr->off = 0;
+ /*-
+ * So at this point the following is true
+ * ssl->s3->rrec.type is the type of record
+ * ssl->s3->rrec.length == number of bytes in record
+ * ssl->s3->rrec.off == offset to first valid byte
+ * ssl->s3->rrec.data == where to take bytes from, increment
+ * after use :-).
+ */
+
+ /* we have pulled in a full packet so zero things */
+ s->packet_length = 0;
+ return (1);
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ return (0);
+}
+
+/*-
+ * Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, one packet has been decoded and can be found in
* ssl->s3->rrec.type - is the type of record
- * ssl->s3->rrec.data, - data
+ * ssl->s3->rrec.data, - data
* ssl->s3->rrec.length, - number of bytes
*/
/* used only by dtls1_read_bytes */
int dtls1_get_record(SSL *s)
- {
- int ssl_major,ssl_minor;
- int i,n;
- SSL3_RECORD *rr;
- unsigned char *p = NULL;
- unsigned short version;
- DTLS1_BITMAP *bitmap;
- unsigned int is_next_epoch;
-
- rr= &(s->s3->rrec);
-
- /* The epoch may have changed. If so, process all the
- * pending records. This is a non-blocking operation. */
- if(dtls1_process_buffered_records(s)<0)
- return -1;
-
- /* if we're renegotiating, then there may be buffered records */
- if (dtls1_get_processed_record(s))
- return 1;
-
- /* get something from the wire */
-again:
- /* check if we have the header */
- if ( (s->rstate != SSL_ST_READ_BODY) ||
- (s->packet_length < DTLS1_RT_HEADER_LENGTH))
- {
- n=ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
- /* read timeout is handled by dtls1_read_bytes */
- if (n <= 0) return(n); /* error or non-blocking */
-
- /* this packet contained a partial record, dump it */
- if (s->packet_length != DTLS1_RT_HEADER_LENGTH)
- {
- s->packet_length = 0;
- goto again;
- }
-
- s->rstate=SSL_ST_READ_BODY;
-
- p=s->packet;
-
- /* Pull apart the header into the DTLS1_RECORD */
- rr->type= *(p++);
- ssl_major= *(p++);
- ssl_minor= *(p++);
- version=(ssl_major<<8)|ssl_minor;
-
- /* sequence number is 64 bits, with top 2 bytes = epoch */
- n2s(p,rr->epoch);
-
- memcpy(&(s->s3->read_sequence[2]), p, 6);
- p+=6;
-
- n2s(p,rr->length);
-
- /* Lets check version */
- if (!s->first_packet)
- {
- if (version != s->version)
- {
- /* unexpected version, silently discard */
- rr->length = 0;
- s->packet_length = 0;
- goto again;
- }
- }
-
- if ((version & 0xff00) != (s->version & 0xff00))
- {
- /* wrong version, silently discard record */
- rr->length = 0;
- s->packet_length = 0;
- goto again;
- }
-
- if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH)
- {
- /* record too long, silently discard it */
- rr->length = 0;
- s->packet_length = 0;
- goto again;
- }
-
- /* now s->rstate == SSL_ST_READ_BODY */
- }
-
- /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
-
- if (rr->length > s->packet_length-DTLS1_RT_HEADER_LENGTH)
- {
- /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
- i=rr->length;
- n=ssl3_read_n(s,i,i,1);
- /* this packet contained a partial record, dump it */
- if ( n != i)
- {
- rr->length = 0;
- s->packet_length = 0;
- goto again;
- }
-
- /* now n == rr->length,
- * and s->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length */
- }
- s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */
-
- /* match epochs. NULL means the packet is dropped on the floor */
- bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
- if ( bitmap == NULL)
- {
- rr->length = 0;
- s->packet_length = 0; /* dump this record */
- goto again; /* get another record */
- }
+{
+ int ssl_major, ssl_minor;
+ int i, n;
+ SSL3_RECORD *rr;
+ unsigned char *p = NULL;
+ unsigned short version;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+
+ rr = &(s->s3->rrec);
+
+ /*
+ * The epoch may have changed. If so, process all the pending records.
+ * This is a non-blocking operation.
+ */
+ if (dtls1_process_buffered_records(s) < 0)
+ return -1;
+
+ /* if we're renegotiating, then there may be buffered records */
+ if (dtls1_get_processed_record(s))
+ return 1;
+
+ /* get something from the wire */
+ again:
+ /* check if we have the header */
+ if ((s->rstate != SSL_ST_READ_BODY) ||
+ (s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
+ n = ssl3_read_n(s, DTLS1_RT_HEADER_LENGTH, s->s3->rbuf.len, 0);
+ /* read timeout is handled by dtls1_read_bytes */
+ if (n <= 0)
+ return (n); /* error or non-blocking */
+
+ /* this packet contained a partial record, dump it */
+ if (s->packet_length != DTLS1_RT_HEADER_LENGTH) {
+ s->packet_length = 0;
+ goto again;
+ }
+
+ s->rstate = SSL_ST_READ_BODY;
+
+ p = s->packet;
+
+ /* Pull apart the header into the DTLS1_RECORD */
+ rr->type = *(p++);
+ ssl_major = *(p++);
+ ssl_minor = *(p++);
+ version = (ssl_major << 8) | ssl_minor;
+
+ /* sequence number is 64 bits, with top 2 bytes = epoch */
+ n2s(p, rr->epoch);
+
+ memcpy(&(s->s3->read_sequence[2]), p, 6);
+ p += 6;
+
+ n2s(p, rr->length);
+
+ /* Lets check version */
+ if (!s->first_packet) {
+ if (version != s->version) {
+ /* unexpected version, silently discard */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+ }
+
+ if ((version & 0xff00) != (s->version & 0xff00)) {
+ /* wrong version, silently discard record */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
+ /* record too long, silently discard it */
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ /* now s->rstate == SSL_ST_READ_BODY */
+ }
+
+ /* s->rstate == SSL_ST_READ_BODY, get and decode the data */
+
+ if (rr->length > s->packet_length - DTLS1_RT_HEADER_LENGTH) {
+ /* now s->packet_length == DTLS1_RT_HEADER_LENGTH */
+ i = rr->length;
+ n = ssl3_read_n(s, i, i, 1);
+ /* this packet contained a partial record, dump it */
+ if (n != i) {
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+ /*
+ * now n == rr->length, and s->packet_length ==
+ * DTLS1_RT_HEADER_LENGTH + rr->length
+ */
+ }
+ s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */
+
+ /* match epochs. NULL means the packet is dropped on the floor */
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
#ifndef OPENSSL_NO_SCTP
- /* Only do replay check if no SCTP bio */
- if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
- {
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
- /* Check whether this is a repeat, or aged record.
- * Don't check if we're listening and this message is
- * a ClientHello. They can look as if they're replayed,
- * since they arrive from different connections and
- * would be dropped unnecessarily.
- */
- if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
- s->packet_length > DTLS1_RT_HEADER_LENGTH &&
- s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
- !dtls1_record_replay_check(s, bitmap))
- {
- rr->length = 0;
- s->packet_length=0; /* dump this record */
- goto again; /* get another record */
- }
+ /*
+ * Check whether this is a repeat, or aged record. Don't check if
+ * we're listening and this message is a ClientHello. They can look
+ * as if they're replayed, since they arrive from different
+ * connections and would be dropped unnecessarily.
+ */
+ if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
+ s->packet_length > DTLS1_RT_HEADER_LENGTH &&
+ s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) &&
+ !dtls1_record_replay_check(s, bitmap)) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
#ifndef OPENSSL_NO_SCTP
- }
+ }
#endif
- /* just read a 0 length packet */
- if (rr->length == 0) goto again;
-
- /* If this record is from the next epoch (either HM or ALERT),
- * and a handshake is currently in progress, buffer it since it
- * cannot be processed at this time. However, do not buffer
- * anything while listening.
- */
- if (is_next_epoch)
- {
- if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen)
- {
- if(dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), rr->seq_num)<0)
- return -1;
- dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
- }
- rr->length = 0;
- s->packet_length = 0;
- goto again;
- }
-
- if (!dtls1_process_record(s))
- {
- rr->length = 0;
- s->packet_length = 0; /* dump this record */
- goto again; /* get another record */
- }
- dtls1_record_bitmap_update(s, bitmap);/* Mark receipt of record. */
-
- return(1);
-
- }
-
-/* Return up to 'len' payload bytes received in 'type' records.
+ /* just read a 0 length packet */
+ if (rr->length == 0)
+ goto again;
+
+ /*
+ * If this record is from the next epoch (either HM or ALERT), and a
+ * handshake is currently in progress, buffer it since it cannot be
+ * processed at this time. However, do not buffer anything while
+ * listening.
+ */
+ if (is_next_epoch) {
+ if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) {
+ if (dtls1_buffer_record
+ (s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
+ return -1;
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+ }
+ rr->length = 0;
+ s->packet_length = 0;
+ goto again;
+ }
+
+ if (!dtls1_process_record(s)) {
+ rr->length = 0;
+ s->packet_length = 0; /* dump this record */
+ goto again; /* get another record */
+ }
+ dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
+
+ return (1);
+
+}
+
+/*-
+ * Return up to 'len' payload bytes received in 'type' records.
* 'type' is one of the following:
*
* - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
@@ -754,1057 +765,1049 @@ again:
* none of our business
*/
int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
- {
- int al,i,j,ret;
- unsigned int n;
- SSL3_RECORD *rr;
- void (*cb)(const SSL *ssl,int type2,int val)=NULL;
+{
+ int al, i, j, ret;
+ unsigned int n;
+ SSL3_RECORD *rr;
+ void (*cb) (const SSL *ssl, int type2, int val) = NULL;
- if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
- if (!ssl3_setup_buffers(s))
- return(-1);
+ if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
+ if (!ssl3_setup_buffers(s))
+ return (-1);
/* XXX: check what the second '&& type' is about */
- if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
- (type != SSL3_RT_HANDSHAKE) && type) ||
- (peek && (type != SSL3_RT_APPLICATION_DATA)))
- {
- SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
- return -1;
- }
+ if ((type && (type != SSL3_RT_APPLICATION_DATA) &&
+ (type != SSL3_RT_HANDSHAKE) && type) ||
+ (peek && (type != SSL3_RT_APPLICATION_DATA))) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
- /* check whether there's a handshake message (client hello?) waiting */
- if ( (ret = have_handshake_fragment(s, type, buf, len, peek)))
- return ret;
+ /*
+ * check whether there's a handshake message (client hello?) waiting
+ */
+ if ((ret = have_handshake_fragment(s, type, buf, len, peek)))
+ return ret;
- /* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+ /*
+ * Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
+ */
#ifndef OPENSSL_NO_SCTP
- /* Continue handshake if it had to be interrupted to read
- * app data with SCTP.
- */
- if ((!s->in_handshake && SSL_in_init(s)) ||
- (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK) &&
- s->s3->in_read_app_data != 2))
+ /*
+ * Continue handshake if it had to be interrupted to read app data with
+ * SCTP.
+ */
+ if ((!s->in_handshake && SSL_in_init(s)) ||
+ (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
+ || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)
+ && s->s3->in_read_app_data != 2))
#else
- if (!s->in_handshake && SSL_in_init(s))
+ if (!s->in_handshake && SSL_in_init(s))
#endif
- {
- /* type == SSL3_RT_APPLICATION_DATA */
- i=s->handshake_func(s);
- if (i < 0) return(i);
- if (i == 0)
- {
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
- return(-1);
- }
- }
-
-start:
- s->rwstate=SSL_NOTHING;
-
- /* s->s3->rrec.type - is the type of record
- * s->s3->rrec.data, - data
- * s->s3->rrec.off, - offset into 'data' for next read
- * s->s3->rrec.length, - number of bytes. */
- rr = &(s->s3->rrec);
-
- /* We are not handshaking and have no data yet,
- * so process data buffered during the last handshake
- * in advance, if any.
- */
- if (s->state == SSL_ST_OK && rr->length == 0)
- {
- pitem *item;
- item = pqueue_pop(s->d1->buffered_app_data.q);
- if (item)
- {
+ {
+ /* type == SSL3_RT_APPLICATION_DATA */
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+ }
+
+ start:
+ s->rwstate = SSL_NOTHING;
+
+ /*-
+ * s->s3->rrec.type - is the type of record
+ * s->s3->rrec.data, - data
+ * s->s3->rrec.off, - offset into 'data' for next read
+ * s->s3->rrec.length, - number of bytes.
+ */
+ rr = &(s->s3->rrec);
+
+ /*
+ * We are not handshaking and have no data yet, so process data buffered
+ * during the last handshake in advance, if any.
+ */
+ if (s->state == SSL_ST_OK && rr->length == 0) {
+ pitem *item;
+ item = pqueue_pop(s->d1->buffered_app_data.q);
+ if (item) {
#ifndef OPENSSL_NO_SCTP
- /* Restore bio_dgram_sctp_rcvinfo struct */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s)))
- {
- DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *) item->data;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo);
- }
+ /* Restore bio_dgram_sctp_rcvinfo struct */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s))) {
+ DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *)item->data;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO,
+ sizeof(rdata->recordinfo), &rdata->recordinfo);
+ }
#endif
- dtls1_copy_record(s, item);
-
- OPENSSL_free(item->data);
- pitem_free(item);
- }
- }
-
- /* Check for timeout */
- if (dtls1_handle_timeout(s) > 0)
- goto start;
-
- /* get new packet if necessary */
- if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
- {
- ret=dtls1_get_record(s);
- if (ret <= 0)
- {
- ret = dtls1_read_failed(s, ret);
- /* anything other than a timeout is an error */
- if (ret <= 0)
- return(ret);
- else
- goto start;
- }
- }
-
- if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE)
- {
- rr->length = 0;
- goto start;
- }
-
- /* we now have a packet which can be read and processed */
-
- if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
- * reset by ssl3_get_finished */
- && (rr->type != SSL3_RT_HANDSHAKE))
- {
- /* We now have application data between CCS and Finished.
- * Most likely the packets were reordered on their way, so
- * buffer the application data for later processing rather
- * than dropping the connection.
- */
- if(dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num)<0)
- {
- SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- rr->length = 0;
- goto start;
- }
-
- /* If the other end has shut down, throw anything we read away
- * (even in 'peek' mode) */
- if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
- {
- rr->length=0;
- s->rwstate=SSL_NOTHING;
- return(0);
- }
-
-
- if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */
- {
- /* make sure that we are not getting application data when we
- * are doing a handshake for the first time */
- if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
- (s->enc_read_ctx == NULL))
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
- goto f_err;
- }
-
- if (len <= 0) return(len);
-
- if ((unsigned int)len > rr->length)
- n = rr->length;
- else
- n = (unsigned int)len;
-
- memcpy(buf,&(rr->data[rr->off]),n);
- if (!peek)
- {
- rr->length-=n;
- rr->off+=n;
- if (rr->length == 0)
- {
- s->rstate=SSL_ST_READ_HEADER;
- rr->off=0;
- }
- }
+ dtls1_copy_record(s, item);
+
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+ }
+
+ /* Check for timeout */
+ if (dtls1_handle_timeout(s) > 0)
+ goto start;
+
+ /* get new packet if necessary */
+ if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) {
+ ret = dtls1_get_record(s);
+ if (ret <= 0) {
+ ret = dtls1_read_failed(s, ret);
+ /* anything other than a timeout is an error */
+ if (ret <= 0)
+ return (ret);
+ else
+ goto start;
+ }
+ }
+
+ if (s->d1->listen && rr->type != SSL3_RT_HANDSHAKE) {
+ rr->length = 0;
+ goto start;
+ }
+
+ /* we now have a packet which can be read and processed */
+
+ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
+ * reset by ssl3_get_finished */
+ && (rr->type != SSL3_RT_HANDSHAKE)) {
+ /*
+ * We now have application data between CCS and Finished. Most likely
+ * the packets were reordered on their way, so buffer the application
+ * data for later processing rather than dropping the connection.
+ */
+ if (dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num) <
+ 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ rr->length = 0;
+ goto start;
+ }
+
+ /*
+ * If the other end has shut down, throw anything we read away (even in
+ * 'peek' mode)
+ */
+ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
+ rr->length = 0;
+ s->rwstate = SSL_NOTHING;
+ return (0);
+ }
+
+ if (type == rr->type) { /* SSL3_RT_APPLICATION_DATA or
+ * SSL3_RT_HANDSHAKE */
+ /*
+ * make sure that we are not getting application data when we are
+ * doing a handshake for the first time
+ */
+ if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
+ (s->enc_read_ctx == NULL)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_APP_DATA_IN_HANDSHAKE);
+ goto f_err;
+ }
+ if (len <= 0)
+ return (len);
+
+ if ((unsigned int)len > rr->length)
+ n = rr->length;
+ else
+ n = (unsigned int)len;
+
+ memcpy(buf, &(rr->data[rr->off]), n);
+ if (!peek) {
+ rr->length -= n;
+ rr->off += n;
+ if (rr->length == 0) {
+ s->rstate = SSL_ST_READ_HEADER;
+ rr->off = 0;
+ }
+ }
#ifndef OPENSSL_NO_SCTP
- /* We were about to renegotiate but had to read
- * belated application data first, so retry.
- */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- rr->type == SSL3_RT_APPLICATION_DATA &&
- (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK))
- {
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- }
-
- /* We might had to delay a close_notify alert because
- * of reordered app data. If there was an alert and there
- * is no message to read anymore, finally set shutdown.
- */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
- {
- s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- return(0);
- }
-#endif
- return(n);
- }
-
-
- /* If we get here, then type != rr->type; if we have a handshake
- * message, then it was unexpected (Hello Request or Client Hello). */
-
- /* In case of record types for which we have 'fragment' storage,
- * fill that so that we can process the data at a fixed place.
- */
- {
- unsigned int k, dest_maxlen = 0;
- unsigned char *dest = NULL;
- unsigned int *dest_len = NULL;
-
- if (rr->type == SSL3_RT_HANDSHAKE)
- {
- dest_maxlen = sizeof s->d1->handshake_fragment;
- dest = s->d1->handshake_fragment;
- dest_len = &s->d1->handshake_fragment_len;
- }
- else if (rr->type == SSL3_RT_ALERT)
- {
- dest_maxlen = sizeof(s->d1->alert_fragment);
- dest = s->d1->alert_fragment;
- dest_len = &s->d1->alert_fragment_len;
- }
+ /*
+ * We were about to renegotiate but had to read belated application
+ * data first, so retry.
+ */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ rr->type == SSL3_RT_APPLICATION_DATA &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
+ || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)) {
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ }
+
+ /*
+ * We might had to delay a close_notify alert because of reordered
+ * app data. If there was an alert and there is no message to read
+ * anymore, finally set shutdown.
+ */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ s->d1->shutdown_received
+ && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return (0);
+ }
+#endif
+ return (n);
+ }
+
+ /*
+ * If we get here, then type != rr->type; if we have a handshake message,
+ * then it was unexpected (Hello Request or Client Hello).
+ */
+
+ /*
+ * In case of record types for which we have 'fragment' storage, fill
+ * that so that we can process the data at a fixed place.
+ */
+ {
+ unsigned int k, dest_maxlen = 0;
+ unsigned char *dest = NULL;
+ unsigned int *dest_len = NULL;
+
+ if (rr->type == SSL3_RT_HANDSHAKE) {
+ dest_maxlen = sizeof s->d1->handshake_fragment;
+ dest = s->d1->handshake_fragment;
+ dest_len = &s->d1->handshake_fragment_len;
+ } else if (rr->type == SSL3_RT_ALERT) {
+ dest_maxlen = sizeof(s->d1->alert_fragment);
+ dest = s->d1->alert_fragment;
+ dest_len = &s->d1->alert_fragment_len;
+ }
#ifndef OPENSSL_NO_HEARTBEATS
- else if (rr->type == TLS1_RT_HEARTBEAT)
- {
- dtls1_process_heartbeat(s);
-
- /* Exit and notify application to read again */
- rr->length = 0;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- return(-1);
- }
+ else if (rr->type == TLS1_RT_HEARTBEAT) {
+ dtls1_process_heartbeat(s);
+
+ /* Exit and notify application to read again */
+ rr->length = 0;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return (-1);
+ }
#endif
- /* else it's a CCS message, or application data or wrong */
- else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
- {
- /* Application data while renegotiating
- * is allowed. Try again reading.
- */
- if (rr->type == SSL3_RT_APPLICATION_DATA)
- {
- BIO *bio;
- s->s3->in_read_app_data=2;
- bio=SSL_get_rbio(s);
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
-
- /* Not certain if this is the right error handling */
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
- goto f_err;
- }
-
- if (dest_maxlen > 0)
- {
- /* XDTLS: In a pathalogical case, the Client Hello
- * may be fragmented--don't always expect dest_maxlen bytes */
- if ( rr->length < dest_maxlen)
- {
+ /* else it's a CCS message, or application data or wrong */
+ else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /*
+ * Application data while renegotiating is allowed. Try again
+ * reading.
+ */
+ if (rr->type == SSL3_RT_APPLICATION_DATA) {
+ BIO *bio;
+ s->s3->in_read_app_data = 2;
+ bio = SSL_get_rbio(s);
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+
+ /* Not certain if this is the right error handling */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+
+ if (dest_maxlen > 0) {
+ /*
+ * XDTLS: In a pathalogical case, the Client Hello may be
+ * fragmented--don't always expect dest_maxlen bytes
+ */
+ if (rr->length < dest_maxlen) {
#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- /*
- * for normal alerts rr->length is 2, while
- * dest_maxlen is 7 if we were to handle this
- * non-existing alert...
- */
- FIX ME
+ /*
+ * for normal alerts rr->length is 2, while
+ * dest_maxlen is 7 if we were to handle this
+ * non-existing alert...
+ */
+ FIX ME
#endif
- s->rstate=SSL_ST_READ_HEADER;
- rr->length = 0;
- goto start;
- }
-
- /* now move 'n' bytes: */
- for ( k = 0; k < dest_maxlen; k++)
- {
- dest[k] = rr->data[rr->off++];
- rr->length--;
- }
- *dest_len = dest_maxlen;
- }
- }
-
- /* s->d1->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE;
- * s->d1->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT.
- * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */
-
- /* If we are a client, check for an incoming 'Hello Request': */
- if ((!s->server) &&
- (s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
- (s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
- (s->session != NULL) && (s->session->cipher != NULL))
- {
- s->d1->handshake_fragment_len = 0;
-
- if ((s->d1->handshake_fragment[1] != 0) ||
- (s->d1->handshake_fragment[2] != 0) ||
- (s->d1->handshake_fragment[3] != 0))
- {
- al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
- goto err;
- }
-
- /* no need to check sequence number on HELLO REQUEST messages */
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- s->d1->handshake_fragment, 4, s, s->msg_callback_arg);
-
- if (SSL_is_init_finished(s) &&
- !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
- !s->s3->renegotiate)
- {
- s->d1->handshake_read_seq++;
- s->new_session = 1;
- ssl3_renegotiate(s);
- if (ssl3_renegotiate_check(s))
- {
- i=s->handshake_func(s);
- if (i < 0) return(i);
- if (i == 0)
- {
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
- return(-1);
- }
-
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
- }
- }
- /* we either finished a handshake or ignored the request,
- * now try again to obtain the (application) data we were asked for */
- goto start;
- }
-
- if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH)
- {
- int alert_level = s->d1->alert_fragment[0];
- int alert_descr = s->d1->alert_fragment[1];
-
- s->d1->alert_fragment_len = 0;
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_ALERT,
- s->d1->alert_fragment, 2, s, s->msg_callback_arg);
-
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- if (cb != NULL)
- {
- j = (alert_level << 8) | alert_descr;
- cb(s, SSL_CB_READ_ALERT, j);
- }
-
- if (alert_level == 1) /* warning */
- {
- s->s3->warn_alert = alert_descr;
- if (alert_descr == SSL_AD_CLOSE_NOTIFY)
- {
+ s->rstate = SSL_ST_READ_HEADER;
+ rr->length = 0;
+ goto start;
+ }
+
+ /* now move 'n' bytes: */
+ for (k = 0; k < dest_maxlen; k++) {
+ dest[k] = rr->data[rr->off++];
+ rr->length--;
+ }
+ *dest_len = dest_maxlen;
+ }
+ }
+
+ /*-
+ * s->d1->handshake_fragment_len == 12 iff rr->type == SSL3_RT_HANDSHAKE;
+ * s->d1->alert_fragment_len == 7 iff rr->type == SSL3_RT_ALERT.
+ * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
+ */
+
+ /* If we are a client, check for an incoming 'Hello Request': */
+ if ((!s->server) &&
+ (s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+ (s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+ (s->session != NULL) && (s->session->cipher != NULL)) {
+ s->d1->handshake_fragment_len = 0;
+
+ if ((s->d1->handshake_fragment[1] != 0) ||
+ (s->d1->handshake_fragment[2] != 0) ||
+ (s->d1->handshake_fragment[3] != 0)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
+ goto err;
+ }
+
+ /*
+ * no need to check sequence number on HELLO REQUEST messages
+ */
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ s->d1->handshake_fragment, 4, s,
+ s->msg_callback_arg);
+
+ if (SSL_is_init_finished(s) &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
+ !s->s3->renegotiate) {
+ s->d1->handshake_read_seq++;
+ s->new_session = 1;
+ ssl3_renegotiate(s);
+ if (ssl3_renegotiate_check(s)) {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES,
+ SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data,
+ * but we trigger an SSL handshake, we return -1 with
+ * the retry option set. Otherwise renegotiation may
+ * cause nasty problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ }
+ }
+ /*
+ * we either finished a handshake or ignored the request, now try
+ * again to obtain the (application) data we were asked for
+ */
+ goto start;
+ }
+
+ if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
+ int alert_level = s->d1->alert_fragment[0];
+ int alert_descr = s->d1->alert_fragment[1];
+
+ s->d1->alert_fragment_len = 0;
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_ALERT,
+ s->d1->alert_fragment, 2, s, s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (alert_level << 8) | alert_descr;
+ cb(s, SSL_CB_READ_ALERT, j);
+ }
+
+ if (alert_level == SSL3_AL_WARNING) {
+ s->s3->warn_alert = alert_descr;
+ if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
#ifndef OPENSSL_NO_SCTP
- /* With SCTP and streams the socket may deliver app data
- * after a close_notify alert. We have to check this
- * first so that nothing gets discarded.
- */
- if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
- BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
- {
- s->d1->shutdown_received = 1;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- return -1;
- }
+ /*
+ * With SCTP and streams the socket may deliver app data
+ * after a close_notify alert. We have to check this first so
+ * that nothing gets discarded.
+ */
+ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
+ BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->d1->shutdown_received = 1;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return -1;
+ }
#endif
- s->shutdown |= SSL_RECEIVED_SHUTDOWN;
- return(0);
- }
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return (0);
+ }
#if 0
/* XXX: this is a possible improvement in the future */
- /* now check if it's a missing record */
- if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
- {
- unsigned short seq;
- unsigned int frag_off;
- unsigned char *p = &(s->d1->alert_fragment[2]);
-
- n2s(p, seq);
- n2l3(p, frag_off);
-
- dtls1_retransmit_message(s,
- dtls1_get_queue_priority(frag->msg_header.seq, 0),
- frag_off, &found);
- if ( ! found && SSL_in_init(s))
- {
- /* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
- /* requested a message not yet sent,
- send an alert ourselves */
- ssl3_send_alert(s,SSL3_AL_WARNING,
- DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
- }
- }
+ /* now check if it's a missing record */
+ if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
+ unsigned short seq;
+ unsigned int frag_off;
+ unsigned char *p = &(s->d1->alert_fragment[2]);
+
+ n2s(p, seq);
+ n2l3(p, frag_off);
+
+ dtls1_retransmit_message(s,
+ dtls1_get_queue_priority
+ (frag->msg_header.seq, 0), frag_off,
+ &found);
+ if (!found && SSL_in_init(s)) {
+ /*
+ * fprintf( stderr,"in init = %d\n", SSL_in_init(s));
+ */
+ /*
+ * requested a message not yet sent, send an alert
+ * ourselves
+ */
+ ssl3_send_alert(s, SSL3_AL_WARNING,
+ DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+ }
+ }
#endif
- }
- else if (alert_level == 2) /* fatal */
- {
- char tmp[16];
-
- s->rwstate=SSL_NOTHING;
- s->s3->fatal_alert = alert_descr;
- SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr);
- BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr);
- ERR_add_error_data(2,"SSL alert number ",tmp);
- s->shutdown|=SSL_RECEIVED_SHUTDOWN;
- SSL_CTX_remove_session(s->ctx,s->session);
- return(0);
- }
- else
- {
- al=SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
- goto f_err;
- }
-
- goto start;
- }
-
- if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */
- {
- s->rwstate=SSL_NOTHING;
- rr->length=0;
- return(0);
- }
-
- if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
- {
- struct ccs_header_st ccs_hdr;
- unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
-
- dtls1_get_ccs_header(rr->data, &ccs_hdr);
-
- if (s->version == DTLS1_BAD_VER)
- ccs_hdr_len = 3;
-
- /* 'Change Cipher Spec' is just a single byte, so we know
- * exactly what the record payload has to look like */
- /* XDTLS: check that epoch is consistent */
- if ( (rr->length != ccs_hdr_len) ||
- (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
- {
- i=SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
- goto err;
- }
-
- rr->length=0;
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
- rr->data, 1, s, s->msg_callback_arg);
-
- /* We can't process a CCS now, because previous handshake
- * messages are still missing, so just drop it.
- */
- if (!s->d1->change_cipher_spec_ok)
- {
- goto start;
- }
-
- s->d1->change_cipher_spec_ok = 0;
-
- s->s3->change_cipher_spec=1;
- if (!ssl3_do_change_cipher_spec(s))
- goto err;
-
- /* do this whenever CCS is processed */
- dtls1_reset_seq_numbers(s, SSL3_CC_READ);
-
- if (s->version == DTLS1_BAD_VER)
- s->d1->handshake_read_seq++;
+ } else if (alert_level == SSL3_AL_FATAL) {
+ char tmp[16];
+
+ s->rwstate = SSL_NOTHING;
+ s->s3->fatal_alert = alert_descr;
+ SSLerr(SSL_F_DTLS1_READ_BYTES,
+ SSL_AD_REASON_OFFSET + alert_descr);
+ BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
+ ERR_add_error_data(2, "SSL alert number ", tmp);
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ SSL_CTX_remove_session(s->ctx, s->session);
+ return (0);
+ } else {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNKNOWN_ALERT_TYPE);
+ goto f_err;
+ }
+
+ goto start;
+ }
+
+ if (s->shutdown & SSL_SENT_SHUTDOWN) { /* but we have not received a
+ * shutdown */
+ s->rwstate = SSL_NOTHING;
+ rr->length = 0;
+ return (0);
+ }
+
+ if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ struct ccs_header_st ccs_hdr;
+ unsigned int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;
+
+ dtls1_get_ccs_header(rr->data, &ccs_hdr);
+
+ if (s->version == DTLS1_BAD_VER)
+ ccs_hdr_len = 3;
+
+ /*
+ * 'Change Cipher Spec' is just a single byte, so we know exactly
+ * what the record payload has to look like
+ */
+ /* XDTLS: check that epoch is consistent */
+ if ((rr->length != ccs_hdr_len) ||
+ (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS)) {
+ i = SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto err;
+ }
+
+ rr->length = 0;
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
+ rr->data, 1, s, s->msg_callback_arg);
+
+ /*
+ * We can't process a CCS now, because previous handshake messages
+ * are still missing, so just drop it.
+ */
+ if (!s->d1->change_cipher_spec_ok) {
+ goto start;
+ }
+
+ s->d1->change_cipher_spec_ok = 0;
+
+ s->s3->change_cipher_spec = 1;
+ if (!ssl3_do_change_cipher_spec(s))
+ goto err;
+
+ /* do this whenever CCS is processed */
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+ if (s->version == DTLS1_BAD_VER)
+ s->d1->handshake_read_seq++;
#ifndef OPENSSL_NO_SCTP
- /* Remember that a CCS has been received,
- * so that an old key of SCTP-Auth can be
- * deleted when a CCS is sent. Will be ignored
- * if no SCTP is used
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
+ /*
+ * Remember that a CCS has been received, so that an old key of
+ * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no
+ * SCTP is used
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
#endif
- goto start;
- }
-
- /* Unexpected handshake message (Client Hello, or protocol violation) */
- if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
- !s->in_handshake)
- {
- struct hm_header_st msg_hdr;
-
- /* this may just be a stale retransmit */
- dtls1_get_message_header(rr->data, &msg_hdr);
- if( rr->epoch != s->d1->r_epoch)
- {
- rr->length = 0;
- goto start;
- }
-
- /* If we are server, we may have a repeated FINISHED of the
- * client here, then retransmit our CCS and FINISHED.
- */
- if (msg_hdr.type == SSL3_MT_FINISHED)
- {
- if (dtls1_check_timeout_num(s) < 0)
- return -1;
-
- dtls1_retransmit_buffered_messages(s);
- rr->length = 0;
- goto start;
- }
-
- if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
- !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
- {
-#if 0 /* worked only because C operator preferences are not as expected (and
- * because this is not really needed for clients except for detecting
- * protocol violations): */
- s->state=SSL_ST_BEFORE|(s->server)
- ?SSL_ST_ACCEPT
- :SSL_ST_CONNECT;
+ goto start;
+ }
+
+ /*
+ * Unexpected handshake message (Client Hello, or protocol violation)
+ */
+ if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+ !s->in_handshake) {
+ struct hm_header_st msg_hdr;
+
+ /* this may just be a stale retransmit */
+ dtls1_get_message_header(rr->data, &msg_hdr);
+ if (rr->epoch != s->d1->r_epoch) {
+ rr->length = 0;
+ goto start;
+ }
+
+ /*
+ * If we are server, we may have a repeated FINISHED of the client
+ * here, then retransmit our CCS and FINISHED.
+ */
+ if (msg_hdr.type == SSL3_MT_FINISHED) {
+ if (dtls1_check_timeout_num(s) < 0)
+ return -1;
+
+ dtls1_retransmit_buffered_messages(s);
+ rr->length = 0;
+ goto start;
+ }
+
+ if (((s->state & SSL_ST_MASK) == SSL_ST_OK) &&
+ !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) {
+#if 0 /* worked only because C operator preferences
+ * are not as expected (and because this is
+ * not really needed for clients except for
+ * detecting protocol violations): */
+ s->state = SSL_ST_BEFORE | (s->server)
+ ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
#else
- s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
+ s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
#endif
- s->renegotiate=1;
- s->new_session=1;
- }
- i=s->handshake_func(s);
- if (i < 0) return(i);
- if (i == 0)
- {
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
- return(-1);
- }
-
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
- goto start;
- }
-
- switch (rr->type)
- {
- default:
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return (-1);
+ }
+
+ if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+ if (s->s3->rbuf.left == 0) { /* no read-ahead left? */
+ BIO *bio;
+ /*
+ * In the case where we try to read application data, but we
+ * trigger an SSL handshake, we return -1 with the retry
+ * option set. Otherwise renegotiation may cause nasty
+ * problems in the blocking world
+ */
+ s->rwstate = SSL_READING;
+ bio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(bio);
+ BIO_set_retry_read(bio);
+ return (-1);
+ }
+ }
+ goto start;
+ }
+
+ switch (rr->type) {
+ default:
#ifndef OPENSSL_NO_TLS
- /* TLS just ignores unknown message types */
- if (s->version == TLS1_VERSION)
- {
- rr->length = 0;
- goto start;
- }
+ /* TLS just ignores unknown message types */
+ if (s->version == TLS1_VERSION) {
+ rr->length = 0;
+ goto start;
+ }
#endif
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
- goto f_err;
- case SSL3_RT_CHANGE_CIPHER_SPEC:
- case SSL3_RT_ALERT:
- case SSL3_RT_HANDSHAKE:
- /* we already handled all of these, with the possible exception
- * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that
- * should not happen when type != rr->type */
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,ERR_R_INTERNAL_ERROR);
- goto f_err;
- case SSL3_RT_APPLICATION_DATA:
- /* At this point, we were expecting handshake data,
- * but have application data. If the library was
- * running inside ssl3_read() (i.e. in_read_app_data
- * is set) and it makes sense to read application data
- * at this point (session renegotiation not yet started),
- * we will indulge it.
- */
- if (s->s3->in_read_app_data &&
- (s->s3->total_renegotiations != 0) &&
- ((
- (s->state & SSL_ST_CONNECT) &&
- (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
- (s->state <= SSL3_ST_CR_SRVR_HELLO_A)
- ) || (
- (s->state & SSL_ST_ACCEPT) &&
- (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
- (s->state >= SSL3_ST_SR_CLNT_HELLO_A)
- )
- ))
- {
- s->s3->in_read_app_data=2;
- return(-1);
- }
- else
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
- goto f_err;
- }
- }
- /* not reached */
-
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
-err:
- return(-1);
- }
-
-int
-dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
- {
- int i;
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
+ case SSL3_RT_ALERT:
+ case SSL3_RT_HANDSHAKE:
+ /*
+ * we already handled all of these, with the possible exception of
+ * SSL3_RT_HANDSHAKE when s->in_handshake is set, but that should not
+ * happen when type != rr->type
+ */
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ case SSL3_RT_APPLICATION_DATA:
+ /*
+ * At this point, we were expecting handshake data, but have
+ * application data. If the library was running inside ssl3_read()
+ * (i.e. in_read_app_data is set) and it makes sense to read
+ * application data at this point (session renegotiation not yet
+ * started), we will indulge it.
+ */
+ if (s->s3->in_read_app_data &&
+ (s->s3->total_renegotiations != 0) &&
+ (((s->state & SSL_ST_CONNECT) &&
+ (s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
+ (s->state <= SSL3_ST_CR_SRVR_HELLO_A)
+ ) || ((s->state & SSL_ST_ACCEPT) &&
+ (s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
+ (s->state >= SSL3_ST_SR_CLNT_HELLO_A)
+ )
+ )) {
+ s->s3->in_read_app_data = 2;
+ return (-1);
+ } else {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_UNEXPECTED_RECORD);
+ goto f_err;
+ }
+ }
+ /* not reached */
+
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ err:
+ return (-1);
+}
+
+int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
+{
+ int i;
#ifndef OPENSSL_NO_SCTP
- /* Check if we have to continue an interrupted handshake
- * for reading belated app data with SCTP.
- */
- if ((SSL_in_init(s) && !s->in_handshake) ||
- (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
- (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)))
+ /*
+ * Check if we have to continue an interrupted handshake for reading
+ * belated app data with SCTP.
+ */
+ if ((SSL_in_init(s) && !s->in_handshake) ||
+ (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK
+ || s->state == DTLS1_SCTP_ST_CR_READ_SOCK)))
#else
- if (SSL_in_init(s) && !s->in_handshake)
+ if (SSL_in_init(s) && !s->in_handshake)
#endif
- {
- i=s->handshake_func(s);
- if (i < 0) return(i);
- if (i == 0)
- {
- SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
- }
- }
-
- if (len > SSL3_RT_MAX_PLAIN_LENGTH)
- {
- SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,SSL_R_DTLS_MESSAGE_TOO_BIG);
- return -1;
- }
-
- i = dtls1_write_bytes(s, type, buf_, len);
- return i;
- }
-
-
- /* this only happens when a client hello is received and a handshake
- * is started. */
+ {
+ i = s->handshake_func(s);
+ if (i < 0)
+ return (i);
+ if (i == 0) {
+ SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES,
+ SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
+ }
+
+ if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ SSLerr(SSL_F_DTLS1_WRITE_APP_DATA_BYTES, SSL_R_DTLS_MESSAGE_TOO_BIG);
+ return -1;
+ }
+
+ i = dtls1_write_bytes(s, type, buf_, len);
+ return i;
+}
+
+ /*
+ * this only happens when a client hello is received and a handshake
+ * is started.
+ */
static int
-have_handshake_fragment(SSL *s, int type, unsigned char *buf,
- int len, int peek)
- {
-
- if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
- /* (partially) satisfy request from storage */
- {
- unsigned char *src = s->d1->handshake_fragment;
- unsigned char *dst = buf;
- unsigned int k,n;
-
- /* peek == 0 */
- n = 0;
- while ((len > 0) && (s->d1->handshake_fragment_len > 0))
- {
- *dst++ = *src++;
- len--; s->d1->handshake_fragment_len--;
- n++;
- }
- /* move any remaining fragment bytes: */
- for (k = 0; k < s->d1->handshake_fragment_len; k++)
- s->d1->handshake_fragment[k] = *src++;
- return n;
- }
-
- return 0;
- }
-
-
-
-
-/* Call this to write data in records of type 'type'
- * It will return <= 0 if not all data has been sent or non-blocking IO.
+have_handshake_fragment(SSL *s, int type, unsigned char *buf,
+ int len, int peek)
+{
+
+ if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
+ /* (partially) satisfy request from storage */
+ {
+ unsigned char *src = s->d1->handshake_fragment;
+ unsigned char *dst = buf;
+ unsigned int k, n;
+
+ /* peek == 0 */
+ n = 0;
+ while ((len > 0) && (s->d1->handshake_fragment_len > 0)) {
+ *dst++ = *src++;
+ len--;
+ s->d1->handshake_fragment_len--;
+ n++;
+ }
+ /* move any remaining fragment bytes: */
+ for (k = 0; k < s->d1->handshake_fragment_len; k++)
+ s->d1->handshake_fragment[k] = *src++;
+ return n;
+ }
+
+ return 0;
+}
+
+/*
+ * Call this to write data in records of type 'type' It will return <= 0 if
+ * not all data has been sent or non-blocking IO.
*/
int dtls1_write_bytes(SSL *s, int type, const void *buf, int len)
- {
- int i;
-
- OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
- s->rwstate=SSL_NOTHING;
- i=do_dtls1_write(s, type, buf, len, 0);
- return i;
- }
-
-int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment)
- {
- unsigned char *p,*pseq;
- int i,mac_size,clear=0;
- int prefix_len = 0;
- SSL3_RECORD *wr;
- SSL3_BUFFER *wb;
- SSL_SESSION *sess;
- int bs;
-
- /* first check if there is a SSL3_BUFFER still being written
- * out. This will happen with non blocking IO */
- if (s->s3->wbuf.left != 0)
- {
- OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */
- return(ssl3_write_pending(s,type,buf,len));
- }
-
- /* If we have an alert to send, lets send it */
- if (s->s3->alert_dispatch)
- {
- i=s->method->ssl_dispatch_alert(s);
- if (i <= 0)
- return(i);
- /* if it went, fall through and send more stuff */
- }
-
- if (len == 0 && !create_empty_fragment)
- return 0;
-
- wr= &(s->s3->wrec);
- wb= &(s->s3->wbuf);
- sess=s->session;
-
- if ( (sess == NULL) ||
- (s->enc_write_ctx == NULL) ||
- (EVP_MD_CTX_md(s->write_hash) == NULL))
- clear=1;
-
- if (clear)
- mac_size=0;
- else
- {
- mac_size=EVP_MD_CTX_size(s->write_hash);
- if (mac_size < 0)
- goto err;
- }
-
- /* DTLS implements explicit IV, so no need for empty fragments */
+{
+ int i;
+
+ OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+ s->rwstate = SSL_NOTHING;
+ i = do_dtls1_write(s, type, buf, len, 0);
+ return i;
+}
+
+int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
+ unsigned int len, int create_empty_fragment)
+{
+ unsigned char *p, *pseq;
+ int i, mac_size, clear = 0;
+ int prefix_len = 0;
+ SSL3_RECORD *wr;
+ SSL3_BUFFER *wb;
+ SSL_SESSION *sess;
+ int bs;
+
+ /*
+ * first check if there is a SSL3_BUFFER still being written out. This
+ * will happen with non blocking IO
+ */
+ if (s->s3->wbuf.left != 0) {
+ OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */
+ return (ssl3_write_pending(s, type, buf, len));
+ }
+
+ /* If we have an alert to send, lets send it */
+ if (s->s3->alert_dispatch) {
+ i = s->method->ssl_dispatch_alert(s);
+ if (i <= 0)
+ return (i);
+ /* if it went, fall through and send more stuff */
+ }
+
+ if (len == 0 && !create_empty_fragment)
+ return 0;
+
+ wr = &(s->s3->wrec);
+ wb = &(s->s3->wbuf);
+ sess = s->session;
+
+ if ((sess == NULL) ||
+ (s->enc_write_ctx == NULL) || (EVP_MD_CTX_md(s->write_hash) == NULL))
+ clear = 1;
+
+ if (clear)
+ mac_size = 0;
+ else {
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ if (mac_size < 0)
+ goto err;
+ }
+
+ /* DTLS implements explicit IV, so no need for empty fragments */
#if 0
- /* 'create_empty_fragment' is true only when this function calls itself */
- if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
- && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
- {
- /* countermeasure against known-IV weakness in CBC ciphersuites
- * (see http://www.openssl.org/~bodo/tls-cbc.txt)
- */
-
- if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA)
- {
- /* recursive function call with 'create_empty_fragment' set;
- * this prepares and buffers the data for an empty fragment
- * (these 'prefix_len' bytes are sent out later
- * together with the actual payload) */
- prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1);
- if (prefix_len <= 0)
- goto err;
-
- if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE)
- {
- /* insufficient space */
- SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- s->s3->empty_fragment_done = 1;
- }
-#endif
- p = wb->buf + prefix_len;
-
- /* write the header */
-
- *(p++)=type&0xff;
- wr->type=type;
-
- *(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;
-
- wr->data=p + bs; /* make room for IV in case of CBC */
- wr->length=(int)len;
- wr->input=(unsigned char *)buf;
-
- /* we now 'read' from wr->input, wr->length bytes into
- * wr->data */
-
- /* first we compress */
- if (s->compress != NULL)
- {
- if (!ssl3_do_compress(s))
- {
- SSLerr(SSL_F_DO_DTLS1_WRITE,SSL_R_COMPRESSION_FAILURE);
- goto err;
- }
- }
- else
- {
- memcpy(wr->data,wr->input,wr->length);
- wr->input=wr->data;
- }
-
- /* we should still have the output to wr->data and the input
- * from wr->input. Length should be wr->length.
- * wr->data still points in the wb->buf */
-
- if (mac_size != 0)
- {
- if(s->method->ssl3_enc->mac(s,&(p[wr->length + bs]),1) < 0)
- goto err;
- wr->length+=mac_size;
- }
-
- /* this is true regardless of mac size */
- 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(s->method->ssl3_enc->enc(s,1) < 1) goto err;
-
- /* record length after mac and block padding */
-/* if (type == SSL3_RT_APPLICATION_DATA ||
- (type == SSL3_RT_ALERT && ! SSL_in_init(s))) */
-
- /* there's only one epoch between handshake and app data */
-
- s2n(s->d1->w_epoch, pseq);
-
- /* XDTLS: ?? */
-/* else
- s2n(s->d1->handshake_epoch, pseq); */
-
- memcpy(pseq, &(s->s3->write_sequence[2]), 6);
- pseq+=6;
- s2n(wr->length,pseq);
-
- /* we should now have
- * wr->data pointing to the encrypted data, which is
- * wr->length long */
- wr->type=type; /* not needed but helps for debugging */
- wr->length+=DTLS1_RT_HEADER_LENGTH;
-
-#if 0 /* this is now done at the message layer */
- /* buffer the record, making it easy to handle retransmits */
- if ( type == SSL3_RT_HANDSHAKE || type == SSL3_RT_CHANGE_CIPHER_SPEC)
- dtls1_buffer_record(s, wr->data, wr->length,
- *((PQ_64BIT *)&(s->s3->write_sequence[0])));
+ /*
+ * 'create_empty_fragment' is true only when this function calls itself
+ */
+ if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
+ && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
+ {
+ /*
+ * countermeasure against known-IV weakness in CBC ciphersuites (see
+ * http://www.openssl.org/~bodo/tls-cbc.txt)
+ */
+
+ if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) {
+ /*
+ * recursive function call with 'create_empty_fragment' set; this
+ * prepares and buffers the data for an empty fragment (these
+ * 'prefix_len' bytes are sent out later together with the actual
+ * payload)
+ */
+ prefix_len = s->method->do_ssl_write(s, type, buf, 0, 1);
+ if (prefix_len <= 0)
+ goto err;
+
+ if (s->s3->wbuf.len <
+ (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE) {
+ /* insufficient space */
+ SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ s->s3->empty_fragment_done = 1;
+ }
#endif
+ p = wb->buf + prefix_len;
- ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+ /* write the header */
- if (create_empty_fragment)
- {
- /* we are in a recursive call;
- * just return the length, don't write out anything here
- */
- return wr->length;
- }
+ *(p++) = type & 0xff;
+ wr->type = type;
- /* now let's set up wb */
- wb->left = prefix_len + wr->length;
- wb->offset = 0;
+ *(p++) = (s->version >> 8);
+ *(p++) = s->version & 0xff;
- /* memorize arguments so that ssl3_write_pending can detect bad write retries later */
- s->s3->wpend_tot=len;
- s->s3->wpend_buf=buf;
- s->s3->wpend_type=type;
- s->s3->wpend_ret=len;
+ /* field where we are to write out packet epoch, seq num and len */
+ pseq = p;
+ p += 10;
- /* we now just need to write the buffer */
- return ssl3_write_pending(s,type,buf,len);
-err:
- return -1;
- }
+ /* 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;
+ wr->data = p + bs; /* make room for IV in case of CBC */
+ wr->length = (int)len;
+ wr->input = (unsigned char *)buf;
-static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
- {
- int cmp;
- unsigned int shift;
- const unsigned char *seq = s->s3->read_sequence;
-
- cmp = satsub64be(seq,bitmap->max_seq_num);
- if (cmp > 0)
- {
- memcpy (s->s3->rrec.seq_num,seq,8);
- return 1; /* this record in new */
- }
- shift = -cmp;
- if (shift >= sizeof(bitmap->map)*8)
- return 0; /* stale, outside the window */
- else if (bitmap->map & (1UL<<shift))
- return 0; /* record previously received */
-
- memcpy (s->s3->rrec.seq_num,seq,8);
- return 1;
- }
+ /*
+ * we now 'read' from wr->input, wr->length bytes into wr->data
+ */
+ /* first we compress */
+ if (s->compress != NULL) {
+ if (!ssl3_do_compress(s)) {
+ SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_COMPRESSION_FAILURE);
+ goto err;
+ }
+ } else {
+ memcpy(wr->data, wr->input, wr->length);
+ wr->input = wr->data;
+ }
-static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
- {
- int cmp;
- unsigned int shift;
- const unsigned char *seq = s->s3->read_sequence;
-
- cmp = satsub64be(seq,bitmap->max_seq_num);
- if (cmp > 0)
- {
- shift = cmp;
- if (shift < sizeof(bitmap->map)*8)
- bitmap->map <<= shift, bitmap->map |= 1UL;
- else
- bitmap->map = 1UL;
- memcpy(bitmap->max_seq_num,seq,8);
- }
- else {
- shift = -cmp;
- if (shift < sizeof(bitmap->map)*8)
- bitmap->map |= 1UL<<shift;
- }
- }
+ /*
+ * we should still have the output to wr->data and the input from
+ * wr->input. Length should be wr->length. wr->data still points in the
+ * wb->buf
+ */
+ if (mac_size != 0) {
+ if (s->method->ssl3_enc->mac(s, &(p[wr->length + bs]), 1) < 0)
+ goto err;
+ wr->length += mac_size;
+ }
-int dtls1_dispatch_alert(SSL *s)
- {
- int i,j;
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- unsigned char buf[DTLS1_AL_HEADER_LENGTH];
- unsigned char *ptr = &buf[0];
+ /* this is true regardless of mac size */
+ 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;
+ }
- s->s3->alert_dispatch=0;
+ if (s->method->ssl3_enc->enc(s, 1) < 1)
+ goto err;
- memset(buf, 0x00, sizeof(buf));
- *ptr++ = s->s3->send_alert[0];
- *ptr++ = s->s3->send_alert[1];
+ /* record length after mac and block padding */
+ /*
+ * if (type == SSL3_RT_APPLICATION_DATA || (type == SSL3_RT_ALERT && !
+ * SSL_in_init(s)))
+ */
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
- {
- s2n(s->d1->handshake_read_seq, ptr);
-#if 0
- if ( s->d1->r_msg_hdr.frag_off == 0) /* waiting for a new msg */
+ /* there's only one epoch between handshake and app data */
- else
- s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */
-#endif
+ s2n(s->d1->w_epoch, pseq);
-#if 0
- fprintf(stderr, "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",s->d1->handshake_read_seq,s->d1->r_msg_hdr.seq);
+ /* XDTLS: ?? */
+ /*
+ * else s2n(s->d1->handshake_epoch, pseq);
+ */
+
+ memcpy(pseq, &(s->s3->write_sequence[2]), 6);
+ pseq += 6;
+ s2n(wr->length, pseq);
+
+ /*
+ * we should now have wr->data pointing to the encrypted data, which is
+ * wr->length long
+ */
+ wr->type = type; /* not needed but helps for debugging */
+ wr->length += DTLS1_RT_HEADER_LENGTH;
+
+#if 0 /* this is now done at the message layer */
+ /* buffer the record, making it easy to handle retransmits */
+ if (type == SSL3_RT_HANDSHAKE || type == SSL3_RT_CHANGE_CIPHER_SPEC)
+ dtls1_buffer_record(s, wr->data, wr->length,
+ *((PQ_64BIT *) & (s->s3->write_sequence[0])));
#endif
- l2n3(s->d1->r_msg_hdr.frag_off, ptr);
- }
+
+ ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+
+ if (create_empty_fragment) {
+ /*
+ * we are in a recursive call; just return the length, don't write
+ * out anything here
+ */
+ return wr->length;
+ }
+
+ /* now let's set up wb */
+ wb->left = prefix_len + wr->length;
+ wb->offset = 0;
+
+ /*
+ * memorize arguments so that ssl3_write_pending can detect bad write
+ * retries later
+ */
+ s->s3->wpend_tot = len;
+ s->s3->wpend_buf = buf;
+ s->s3->wpend_type = type;
+ s->s3->wpend_ret = len;
+
+ /* we now just need to write the buffer */
+ return ssl3_write_pending(s, type, buf, len);
+ err:
+ return -1;
+}
+
+static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = s->s3->read_sequence;
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ memcpy(s->s3->rrec.seq_num, seq, 8);
+ return 1; /* this record in new */
+ }
+ shift = -cmp;
+ if (shift >= sizeof(bitmap->map) * 8)
+ return 0; /* stale, outside the window */
+ else if (bitmap->map & (1UL << shift))
+ return 0; /* record previously received */
+
+ memcpy(s->s3->rrec.seq_num, seq, 8);
+ return 1;
+}
+
+static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
+{
+ int cmp;
+ unsigned int shift;
+ const unsigned char *seq = s->s3->read_sequence;
+
+ cmp = satsub64be(seq, bitmap->max_seq_num);
+ if (cmp > 0) {
+ shift = cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map <<= shift, bitmap->map |= 1UL;
+ else
+ bitmap->map = 1UL;
+ memcpy(bitmap->max_seq_num, seq, 8);
+ } else {
+ shift = -cmp;
+ if (shift < sizeof(bitmap->map) * 8)
+ bitmap->map |= 1UL << shift;
+ }
+}
+
+int dtls1_dispatch_alert(SSL *s)
+{
+ int i, j;
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ unsigned char buf[DTLS1_AL_HEADER_LENGTH];
+ unsigned char *ptr = &buf[0];
+
+ s->s3->alert_dispatch = 0;
+
+ memset(buf, 0x00, sizeof(buf));
+ *ptr++ = s->s3->send_alert[0];
+ *ptr++ = s->s3->send_alert[1];
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+ if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
+ s2n(s->d1->handshake_read_seq, ptr);
+# if 0
+ if (s->d1->r_msg_hdr.frag_off == 0)
+ /*
+ * waiting for a new msg
+ */
+ else
+ s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */
+# endif
+
+# if 0
+ fprintf(stderr,
+ "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",
+ s->d1->handshake_read_seq, s->d1->r_msg_hdr.seq);
+# endif
+ l2n3(s->d1->r_msg_hdr.frag_off, ptr);
+ }
#endif
- i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
- if (i <= 0)
- {
- s->s3->alert_dispatch=1;
- /* fprintf( stderr, "not done with alert\n" ); */
- }
- else
- {
- if (s->s3->send_alert[0] == SSL3_AL_FATAL
+ i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf), 0);
+ if (i <= 0) {
+ s->s3->alert_dispatch = 1;
+ /* fprintf( stderr, "not done with alert\n" ); */
+ } else {
+ if (s->s3->send_alert[0] == SSL3_AL_FATAL
#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+ || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
#endif
- )
- (void)BIO_flush(s->wbio);
-
- if (s->msg_callback)
- s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
- 2, s, s->msg_callback_arg);
-
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- if (cb != NULL)
- {
- j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1];
- cb(s,SSL_CB_WRITE_ALERT,j);
- }
- }
- return(i);
- }
-
-
-static DTLS1_BITMAP *
-dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch)
- {
-
+ )
+ (void)BIO_flush(s->wbio);
+
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
+ 2, s, s->msg_callback_arg);
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ if (cb != NULL) {
+ j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
+ cb(s, SSL_CB_WRITE_ALERT, j);
+ }
+ }
+ return (i);
+}
+
+static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
+ unsigned int *is_next_epoch)
+{
+
*is_next_epoch = 0;
/* In current epoch, accept HM, CCS, DATA, & ALERT */
@@ -1813,100 +1816,90 @@ dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch)
/* Only HM and ALERT messages can be from the next epoch */
else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
- (rr->type == SSL3_RT_HANDSHAKE ||
- rr->type == SSL3_RT_ALERT))
- {
+ (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->d1->next_bitmap;
- }
+ }
return NULL;
- }
+}
#if 0
static int
-dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, unsigned short *priority,
- unsigned long *offset)
- {
-
- /* alerts are passed up immediately */
- if ( rr->type == SSL3_RT_APPLICATION_DATA ||
- rr->type == SSL3_RT_ALERT)
- return 0;
-
- /* Only need to buffer if a handshake is underway.
- * (this implies that Hello Request and Client Hello are passed up
- * immediately) */
- if ( SSL_in_init(s))
- {
- unsigned char *data = rr->data;
- /* need to extract the HM/CCS sequence number here */
- if ( rr->type == SSL3_RT_HANDSHAKE ||
- rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
- {
- unsigned short seq_num;
- struct hm_header_st msg_hdr;
- struct ccs_header_st ccs_hdr;
-
- if ( rr->type == SSL3_RT_HANDSHAKE)
- {
- dtls1_get_message_header(data, &msg_hdr);
- seq_num = msg_hdr.seq;
- *offset = msg_hdr.frag_off;
- }
- else
- {
- dtls1_get_ccs_header(data, &ccs_hdr);
- seq_num = ccs_hdr.seq;
- *offset = 0;
- }
-
- /* this is either a record we're waiting for, or a
- * retransmit of something we happened to previously
- * receive (higher layers will drop the repeat silently */
- if ( seq_num < s->d1->handshake_read_seq)
- return 0;
- if (rr->type == SSL3_RT_HANDSHAKE &&
- seq_num == s->d1->handshake_read_seq &&
- msg_hdr.frag_off < s->d1->r_msg_hdr.frag_off)
- return 0;
- else if ( seq_num == s->d1->handshake_read_seq &&
- (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC ||
- msg_hdr.frag_off == s->d1->r_msg_hdr.frag_off))
- return 0;
- else
- {
- *priority = seq_num;
- return 1;
- }
- }
- else /* unknown record type */
- return 0;
- }
-
- return 0;
- }
+dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
+ unsigned short *priority, unsigned long *offset)
+{
+
+ /* alerts are passed up immediately */
+ if (rr->type == SSL3_RT_APPLICATION_DATA || rr->type == SSL3_RT_ALERT)
+ return 0;
+
+ /*
+ * Only need to buffer if a handshake is underway. (this implies that
+ * Hello Request and Client Hello are passed up immediately)
+ */
+ if (SSL_in_init(s)) {
+ unsigned char *data = rr->data;
+ /* need to extract the HM/CCS sequence number here */
+ if (rr->type == SSL3_RT_HANDSHAKE ||
+ rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ unsigned short seq_num;
+ struct hm_header_st msg_hdr;
+ struct ccs_header_st ccs_hdr;
+
+ if (rr->type == SSL3_RT_HANDSHAKE) {
+ dtls1_get_message_header(data, &msg_hdr);
+ seq_num = msg_hdr.seq;
+ *offset = msg_hdr.frag_off;
+ } else {
+ dtls1_get_ccs_header(data, &ccs_hdr);
+ seq_num = ccs_hdr.seq;
+ *offset = 0;
+ }
+
+ /*
+ * this is either a record we're waiting for, or a retransmit of
+ * something we happened to previously receive (higher layers
+ * will drop the repeat silently
+ */
+ if (seq_num < s->d1->handshake_read_seq)
+ return 0;
+ if (rr->type == SSL3_RT_HANDSHAKE &&
+ seq_num == s->d1->handshake_read_seq &&
+ msg_hdr.frag_off < s->d1->r_msg_hdr.frag_off)
+ return 0;
+ else if (seq_num == s->d1->handshake_read_seq &&
+ (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC ||
+ msg_hdr.frag_off == s->d1->r_msg_hdr.frag_off))
+ return 0;
+ else {
+ *priority = seq_num;
+ return 1;
+ }
+ } else /* unknown record type */
+ return 0;
+ }
+
+ return 0;
+}
#endif
-void
-dtls1_reset_seq_numbers(SSL *s, int rw)
- {
- unsigned char *seq;
- unsigned int seq_bytes = sizeof(s->s3->read_sequence);
-
- if ( rw & SSL3_CC_READ)
- {
- seq = s->s3->read_sequence;
- s->d1->r_epoch++;
- memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
- memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
- }
- else
- {
- seq = s->s3->write_sequence;
- memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
- s->d1->w_epoch++;
- }
-
- memset(seq, 0x00, seq_bytes);
- }
+void dtls1_reset_seq_numbers(SSL *s, int rw)
+{
+ unsigned char *seq;
+ unsigned int seq_bytes = sizeof(s->s3->read_sequence);
+
+ if (rw & SSL3_CC_READ) {
+ seq = s->s3->read_sequence;
+ s->d1->r_epoch++;
+ memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
+ memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+ } else {
+ seq = s->s3->write_sequence;
+ memcpy(s->d1->last_write_sequence, seq,
+ sizeof(s->s3->write_sequence));
+ s->d1->w_epoch++;
+ }
+
+ memset(seq, 0x00, seq_bytes);
+}
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index 535539ba3b50..6c6e07ce902b 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -5,21 +5,21 @@
* 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:
@@ -34,10 +34,10 @@
* 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
+ * 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
@@ -49,7 +49,7 @@
* 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
@@ -63,7 +63,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -109,11 +109,10 @@
*
*/
/*
- DTLS code by Eric Rescorla <ekr@rtfm.com>
-
- Copyright (C) 2006, Network Resonance, Inc.
- Copyright (C) 2011, RTFM, Inc.
-*/
+ * DTLS code by Eric Rescorla <ekr@rtfm.com>
+ *
+ * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc.
+ */
#include <stdio.h>
#include <openssl/objects.h>
@@ -121,343 +120,330 @@
#ifndef OPENSSL_NO_SRTP
-#include "srtp.h"
-
+# include "srtp.h"
-static SRTP_PROTECTION_PROFILE srtp_known_profiles[]=
+static SRTP_PROTECTION_PROFILE srtp_known_profiles[] = {
{
+ "SRTP_AES128_CM_SHA1_80",
+ SRTP_AES128_CM_SHA1_80,
+ },
{
- "SRTP_AES128_CM_SHA1_80",
- SRTP_AES128_CM_SHA1_80,
- },
+ "SRTP_AES128_CM_SHA1_32",
+ SRTP_AES128_CM_SHA1_32,
+ },
+# if 0
{
- "SRTP_AES128_CM_SHA1_32",
- SRTP_AES128_CM_SHA1_32,
- },
-#if 0
+ "SRTP_NULL_SHA1_80",
+ SRTP_NULL_SHA1_80,
+ },
{
- "SRTP_NULL_SHA1_80",
- SRTP_NULL_SHA1_80,
- },
- {
- "SRTP_NULL_SHA1_32",
- SRTP_NULL_SHA1_32,
- },
-#endif
+ "SRTP_NULL_SHA1_32",
+ SRTP_NULL_SHA1_32,
+ },
+# endif
{0}
- };
+};
static int find_profile_by_name(char *profile_name,
- SRTP_PROTECTION_PROFILE **pptr,unsigned len)
- {
- SRTP_PROTECTION_PROFILE *p;
-
- p=srtp_known_profiles;
- while(p->name)
- {
- if((len == strlen(p->name)) && !strncmp(p->name,profile_name,
- len))
- {
- *pptr=p;
- return 0;
- }
-
- p++;
- }
-
- return 1;
- }
-
-static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTECTION_PROFILE) **out)
- {
- STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
-
- char *col;
- char *ptr=(char *)profiles_string;
-
- SRTP_PROTECTION_PROFILE *p;
-
- if(!(profiles=sk_SRTP_PROTECTION_PROFILE_new_null()))
- {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
- return 1;
- }
-
- do
- {
- col=strchr(ptr,':');
-
- if(!find_profile_by_name(ptr,&p,
- col ? col-ptr : (int)strlen(ptr)))
- {
- if (sk_SRTP_PROTECTION_PROFILE_find(profiles,p) >= 0)
- {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- sk_SRTP_PROTECTION_PROFILE_free(profiles);
- return 1;
- }
-
- sk_SRTP_PROTECTION_PROFILE_push(profiles,p);
- }
- else
- {
- SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
- sk_SRTP_PROTECTION_PROFILE_free(profiles);
- return 1;
- }
-
- if(col) ptr=col+1;
- } while (col);
-
- *out=profiles;
-
- return 0;
- }
-
-int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,const char *profiles)
- {
- return ssl_ctx_make_profiles(profiles,&ctx->srtp_profiles);
- }
-
-int SSL_set_tlsext_use_srtp(SSL *s,const char *profiles)
- {
- return ssl_ctx_make_profiles(profiles,&s->srtp_profiles);
- }
-
+ SRTP_PROTECTION_PROFILE **pptr, unsigned len)
+{
+ SRTP_PROTECTION_PROFILE *p;
+
+ p = srtp_known_profiles;
+ while (p->name) {
+ if ((len == strlen(p->name)) && !strncmp(p->name, profile_name, len)) {
+ *pptr = p;
+ return 0;
+ }
+
+ p++;
+ }
+
+ return 1;
+}
+
+static int ssl_ctx_make_profiles(const char *profiles_string,
+ STACK_OF(SRTP_PROTECTION_PROFILE) **out)
+{
+ STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
+
+ char *col;
+ char *ptr = (char *)profiles_string;
+
+ SRTP_PROTECTION_PROFILE *p;
+
+ if (!(profiles = sk_SRTP_PROTECTION_PROFILE_new_null())) {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
+ return 1;
+ }
+
+ do {
+ col = strchr(ptr, ':');
+
+ if (!find_profile_by_name(ptr, &p,
+ col ? col - ptr : (int)strlen(ptr))) {
+ if (sk_SRTP_PROTECTION_PROFILE_find(profiles, p) >= 0) {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ sk_SRTP_PROTECTION_PROFILE_free(profiles);
+ return 1;
+ }
+
+ sk_SRTP_PROTECTION_PROFILE_push(profiles, p);
+ } else {
+ SSLerr(SSL_F_SSL_CTX_MAKE_PROFILES,
+ SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
+ sk_SRTP_PROTECTION_PROFILE_free(profiles);
+ return 1;
+ }
+
+ if (col)
+ ptr = col + 1;
+ } while (col);
+
+ *out = profiles;
+
+ return 0;
+}
+
+int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles)
+{
+ return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
+}
+
+int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles)
+{
+ return ssl_ctx_make_profiles(profiles, &s->srtp_profiles);
+}
STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s)
- {
- if(s != NULL)
- {
- if(s->srtp_profiles != NULL)
- {
- return s->srtp_profiles;
- }
- else if((s->ctx != NULL) &&
- (s->ctx->srtp_profiles != NULL))
- {
- return s->ctx->srtp_profiles;
- }
- }
-
- return NULL;
- }
+{
+ if (s != NULL) {
+ if (s->srtp_profiles != NULL) {
+ return s->srtp_profiles;
+ } else if ((s->ctx != NULL) && (s->ctx->srtp_profiles != NULL)) {
+ return s->ctx->srtp_profiles;
+ }
+ }
+
+ return NULL;
+}
SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
- {
- return s->srtp_profile;
- }
-
-/* Note: this function returns 0 length if there are no
- profiles specified */
-int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen)
- {
- int ct=0;
- int i;
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt=0;
- SRTP_PROTECTION_PROFILE *prof;
-
- clnt=SSL_get_srtp_profiles(s);
- ct=sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */
-
- if(p)
- {
- if(ct==0)
- {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST);
- return 1;
- }
-
- if((2 + ct*2 + 1) > maxlen)
- {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
- return 1;
- }
-
- /* Add the length */
- s2n(ct * 2, p);
- for(i=0;i<ct;i++)
- {
- prof=sk_SRTP_PROTECTION_PROFILE_value(clnt,i);
- s2n(prof->id,p);
- }
-
- /* Add an empty use_mki value */
- *p++ = 0;
- }
-
- *len=2 + ct*2 + 1;
-
- return 0;
- }
-
-
-int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al)
- {
- SRTP_PROTECTION_PROFILE *sprof;
- STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
- int ct;
- int mki_len;
- int i, srtp_pref;
- unsigned int id;
-
- /* Length value + the MKI length */
- if(len < 3)
- {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- /* Pull off the length of the cipher suite list */
- n2s(d, ct);
+{
+ return s->srtp_profile;
+}
+
+/*
+ * Note: this function returns 0 length if there are no profiles specified
+ */
+int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ int ct = 0;
+ int i;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = 0;
+ SRTP_PROTECTION_PROFILE *prof;
+
+ clnt = SSL_get_srtp_profiles(s);
+ ct = sk_SRTP_PROTECTION_PROFILE_num(clnt); /* -1 if clnt == 0 */
+
+ if (p) {
+ if (ct == 0) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST);
+ return 1;
+ }
+
+ if ((2 + ct * 2 + 1) > maxlen) {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 1;
+ }
+
+ /* Add the length */
+ s2n(ct * 2, p);
+ for (i = 0; i < ct; i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+ s2n(prof->id, p);
+ }
+
+ /* Add an empty use_mki value */
+ *p++ = 0;
+ }
+
+ *len = 2 + ct * 2 + 1;
+
+ return 0;
+}
+
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
+ int *al)
+{
+ SRTP_PROTECTION_PROFILE *sprof;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
+ int ct;
+ int mki_len;
+ int i, srtp_pref;
+ unsigned int id;
+
+ /* Length value + the MKI length */
+ if (len < 3) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ /* Pull off the length of the cipher suite list */
+ n2s(d, ct);
+ len -= 2;
+
+ /* Check that it is even */
+ if (ct % 2) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ /* Check that lengths are consistent */
+ if (len < (ct + 1)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ srvr = SSL_get_srtp_profiles(s);
+ s->srtp_profile = NULL;
+ /* Search all profiles for a match initially */
+ srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
+
+ while (ct) {
+ n2s(d, id);
+ ct -= 2;
len -= 2;
-
- /* Check that it is even */
- if(ct%2)
- {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- /* Check that lengths are consistent */
- if(len < (ct + 1))
- {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- srvr=SSL_get_srtp_profiles(s);
- s->srtp_profile = NULL;
- /* Search all profiles for a match initially */
- srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
-
- while(ct)
- {
- n2s(d,id);
- ct-=2;
- len-=2;
-
- /*
- * Only look for match in profiles of higher preference than
- * current match.
- * If no profiles have been have been configured then this
- * does nothing.
- */
- for (i = 0; i < srtp_pref; i++)
- {
- sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
- if (sprof->id == id)
- {
- s->srtp_profile = sprof;
- srtp_pref = i;
- break;
- }
- }
- }
-
- /* Now extract the MKI value as a sanity check, but discard it for now */
- mki_len = *d;
- d++; len--;
-
- if (mki_len != len)
- {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_MKI_VALUE);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- return 0;
- }
-
-int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen)
- {
- if(p)
- {
- if(maxlen < 5)
- {
- SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
- return 1;
- }
-
- if(s->srtp_profile==0)
- {
- SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,SSL_R_USE_SRTP_NOT_NEGOTIATED);
- return 1;
- }
- s2n(2, p);
- s2n(s->srtp_profile->id,p);
- *p++ = 0;
- }
- *len=5;
-
- return 0;
- }
-
-
-int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al)
- {
- unsigned id;
- int i;
- int ct;
-
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
- SRTP_PROTECTION_PROFILE *prof;
-
- if(len!=5)
- {
- SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- n2s(d, ct);
- if(ct!=2)
- {
- SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- n2s(d,id);
- if (*d) /* Must be no MKI, since we never offer one */
- {
- SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_MKI_VALUE);
- *al=SSL_AD_ILLEGAL_PARAMETER;
- return 1;
- }
-
- clnt=SSL_get_srtp_profiles(s);
-
- /* Throw an error if the server gave us an unsolicited extension */
- if (clnt == NULL)
- {
- SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_NO_SRTP_PROFILES);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- /* Check to see if the server gave us something we support
- (and presumably offered)
- */
- for(i=0;i<sk_SRTP_PROTECTION_PROFILE_num(clnt);i++)
- {
- prof=sk_SRTP_PROTECTION_PROFILE_value(clnt,i);
-
- if(prof->id == id)
- {
- s->srtp_profile=prof;
- *al=0;
- return 0;
- }
- }
-
- SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al=SSL_AD_DECODE_ERROR;
- return 1;
- }
+ /*
+ * Only look for match in profiles of higher preference than
+ * current match.
+ * If no profiles have been have been configured then this
+ * does nothing.
+ */
+ for (i = 0; i < srtp_pref; i++) {
+ sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
+ if (sprof->id == id) {
+ s->srtp_profile = sprof;
+ srtp_pref = i;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Now extract the MKI value as a sanity check, but discard it for now
+ */
+ mki_len = *d;
+ d++;
+ len--;
+
+ if (mki_len != len) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ return 0;
+}
+
+int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
+ int maxlen)
+{
+ if (p) {
+ if (maxlen < 5) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
+ return 1;
+ }
+
+ if (s->srtp_profile == 0) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_USE_SRTP_NOT_NEGOTIATED);
+ return 1;
+ }
+ s2n(2, p);
+ s2n(s->srtp_profile->id, p);
+ *p++ = 0;
+ }
+ *len = 5;
+
+ return 0;
+}
+
+int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
+ int *al)
+{
+ unsigned id;
+ int i;
+ int ct;
+
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
+ SRTP_PROTECTION_PROFILE *prof;
+
+ if (len != 5) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ n2s(d, ct);
+ if (ct != 2) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ n2s(d, id);
+ if (*d) { /* Must be no MKI, since we never offer one */
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 1;
+ }
+
+ clnt = SSL_get_srtp_profiles(s);
+
+ /* Throw an error if the server gave us an unsolicited extension */
+ if (clnt == NULL) {
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_NO_SRTP_PROFILES);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
+
+ /*
+ * Check to see if the server gave us something we support (and
+ * presumably offered)
+ */
+ for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+
+ if (prof->id == id) {
+ s->srtp_profile = prof;
+ *al = 0;
+ return 0;
+ }
+ }
+
+ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+}
#endif
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index da4c21e06a1c..c4ec9fe10845 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -1,7 +1,7 @@
/* ssl/d1_srvr.c */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -62,21 +62,21 @@
* 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:
@@ -91,10 +91,10 @@
* 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
+ * 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
@@ -106,7 +106,7 @@
* 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
@@ -123,1624 +123,1618 @@
#include <openssl/md5.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_DH
-#include <openssl/dh.h>
+# include <openssl/dh.h>
#endif
static const SSL_METHOD *dtls1_get_server_method(int ver);
static int dtls1_send_hello_verify_request(SSL *s);
static const SSL_METHOD *dtls1_get_server_method(int ver)
- {
- if (ver == DTLS1_VERSION)
- return(DTLSv1_server_method());
- else
- return(NULL);
- }
+{
+ if (ver == DTLS1_VERSION)
+ return (DTLSv1_server_method());
+ else
+ return (NULL);
+}
IMPLEMENT_dtls1_meth_func(DTLSv1_server_method,
- dtls1_accept,
- ssl_undefined_function,
- dtls1_get_server_method)
+ dtls1_accept,
+ ssl_undefined_function, dtls1_get_server_method)
int dtls1_accept(SSL *s)
- {
- BUF_MEM *buf;
- unsigned long Time=(unsigned long)time(NULL);
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- unsigned long alg_k;
- int ret= -1;
- int new_state,state,skip=0;
- int listen;
+{
+ BUF_MEM *buf;
+ unsigned long Time = (unsigned long)time(NULL);
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ unsigned long alg_k;
+ int ret = -1;
+ int new_state, state, skip = 0;
+ int listen;
#ifndef OPENSSL_NO_SCTP
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif
- RAND_add(&Time,sizeof(Time),0);
- ERR_clear_error();
- clear_sys_error();
+ RAND_add(&Time, sizeof(Time), 0);
+ ERR_clear_error();
+ clear_sys_error();
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- listen = s->d1->listen;
+ listen = s->d1->listen;
- /* init things to blank */
- s->in_handshake++;
- if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+ /* init things to blank */
+ s->in_handshake++;
+ if (!SSL_in_init(s) || SSL_in_before(s))
+ SSL_clear(s);
- s->d1->listen = listen;
+ s->d1->listen = listen;
#ifndef OPENSSL_NO_SCTP
- /* Notify SCTP BIO socket to enter handshake
- * mode and prevent stream identifier other
- * than 0. Will be ignored if no SCTP is used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL);
+ /*
+ * Notify SCTP BIO socket to enter handshake mode and prevent stream
+ * identifier other than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ s->in_handshake, NULL);
#endif
- if (s->cert == NULL)
- {
- SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
- return(-1);
- }
-
+ if (s->cert == NULL) {
+ SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_NO_CERTIFICATE_SET);
+ return (-1);
+ }
#ifndef OPENSSL_NO_HEARTBEATS
- /* If we're awaiting a HeartbeatResponse, pretend we
- * already got and don't await it anymore, because
- * Heartbeats don't make sense during handshakes anyway.
- */
- if (s->tlsext_hb_pending)
- {
- dtls1_stop_timer(s);
- s->tlsext_hb_pending = 0;
- s->tlsext_hb_seq++;
- }
+ /*
+ * If we're awaiting a HeartbeatResponse, pretend we already got and
+ * don't await it anymore, because Heartbeats don't make sense during
+ * handshakes anyway.
+ */
+ if (s->tlsext_hb_pending) {
+ dtls1_stop_timer(s);
+ s->tlsext_hb_pending = 0;
+ s->tlsext_hb_seq++;
+ }
#endif
- for (;;)
- {
- state=s->state;
-
- switch (s->state)
- {
- case SSL_ST_RENEGOTIATE:
- s->renegotiate=1;
- /* s->state=SSL_ST_ACCEPT; */
-
- case SSL_ST_BEFORE:
- case SSL_ST_ACCEPT:
- case SSL_ST_BEFORE|SSL_ST_ACCEPT:
- case SSL_ST_OK|SSL_ST_ACCEPT:
-
- s->server=1;
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
-
- if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00))
- {
- SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->type=SSL_ST_ACCEPT;
-
- if (s->init_buf == NULL)
- {
- if ((buf=BUF_MEM_new()) == NULL)
- {
- ret= -1;
- goto end;
- }
- if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
- {
- BUF_MEM_free(buf);
- ret= -1;
- goto end;
- }
- s->init_buf=buf;
- }
-
- if (!ssl3_setup_buffers(s))
- {
- ret= -1;
- goto end;
- }
-
- s->init_num=0;
- s->d1->change_cipher_spec_ok = 0;
- /* Should have been reset by ssl3_get_finished, too. */
- s->s3->change_cipher_spec = 0;
-
- if (s->state != SSL_ST_RENEGOTIATE)
- {
- /* Ok, we now need to push on a buffering BIO so that
- * the output is sent in a way that TCP likes :-)
- * ...but not with SCTP :-)
- */
+ for (;;) {
+ state = s->state;
+
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ /* s->state=SSL_ST_ACCEPT; */
+
+ case SSL_ST_BEFORE:
+ case SSL_ST_ACCEPT:
+ case SSL_ST_BEFORE | SSL_ST_ACCEPT:
+ case SSL_ST_OK | SSL_ST_ACCEPT:
+
+ s->server = 1;
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+
+ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
+ SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ s->type = SSL_ST_ACCEPT;
+
+ if (s->init_buf == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL) {
+ ret = -1;
+ goto end;
+ }
+ if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ BUF_MEM_free(buf);
+ ret = -1;
+ goto end;
+ }
+ s->init_buf = buf;
+ }
+
+ if (!ssl3_setup_buffers(s)) {
+ ret = -1;
+ goto end;
+ }
+
+ s->init_num = 0;
+ s->d1->change_cipher_spec_ok = 0;
+ /*
+ * Should have been reset by ssl3_get_finished, too.
+ */
+ s->s3->change_cipher_spec = 0;
+
+ if (s->state != SSL_ST_RENEGOTIATE) {
+ /*
+ * Ok, we now need to push on a buffering BIO so that the
+ * output is sent in a way that TCP likes :-) ...but not with
+ * SCTP :-)
+ */
#ifndef OPENSSL_NO_SCTP
- if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
+ if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
#endif
- if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
-
- ssl3_init_finished_mac(s);
- s->state=SSL3_ST_SR_CLNT_HELLO_A;
- s->ctx->stats.sess_accept++;
- }
- else
- {
- /* s->state == SSL_ST_RENEGOTIATE,
- * we will just send a HelloRequest */
- s->ctx->stats.sess_accept_renegotiate++;
- s->state=SSL3_ST_SW_HELLO_REQ_A;
- }
-
- break;
-
- case SSL3_ST_SW_HELLO_REQ_A:
- case SSL3_ST_SW_HELLO_REQ_B:
-
- s->shutdown=0;
- dtls1_clear_record_buffer(s);
- dtls1_start_timer(s);
- ret=dtls1_send_hello_request(s);
- if (ret <= 0) goto end;
- s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
- s->state=SSL3_ST_SW_FLUSH;
- s->init_num=0;
-
- ssl3_init_finished_mac(s);
- break;
-
- case SSL3_ST_SW_HELLO_REQ_C:
- s->state=SSL_ST_OK;
- break;
-
- case SSL3_ST_SR_CLNT_HELLO_A:
- case SSL3_ST_SR_CLNT_HELLO_B:
- case SSL3_ST_SR_CLNT_HELLO_C:
-
- s->shutdown=0;
- ret=ssl3_get_client_hello(s);
- if (ret <= 0) goto end;
- dtls1_stop_timer(s);
-
- if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
- s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
- else
- s->state = SSL3_ST_SW_SRVR_HELLO_A;
-
- s->init_num=0;
-
- /* Reflect ClientHello sequence to remain stateless while listening */
- if (listen)
- {
- memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence));
- }
-
- /* If we're just listening, stop here */
- if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
- {
- ret = 2;
- s->d1->listen = 0;
- /* Set expected sequence numbers
- * to continue the handshake.
- */
- s->d1->handshake_read_seq = 2;
- s->d1->handshake_write_seq = 1;
- s->d1->next_handshake_write_seq = 1;
- goto end;
- }
-
- break;
-
- case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
- case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
-
- ret = dtls1_send_hello_verify_request(s);
- if ( ret <= 0) goto end;
- s->state=SSL3_ST_SW_FLUSH;
- s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
-
- /* HelloVerifyRequest resets Finished MAC */
- if (s->version != DTLS1_BAD_VER)
- ssl3_init_finished_mac(s);
- break;
-
+ if (!ssl_init_wbio_buffer(s, 1)) {
+ ret = -1;
+ goto end;
+ }
+
+ ssl3_init_finished_mac(s);
+ s->state = SSL3_ST_SR_CLNT_HELLO_A;
+ s->ctx->stats.sess_accept++;
+ } else {
+ /*
+ * s->state == SSL_ST_RENEGOTIATE, we will just send a
+ * HelloRequest
+ */
+ s->ctx->stats.sess_accept_renegotiate++;
+ s->state = SSL3_ST_SW_HELLO_REQ_A;
+ }
+
+ break;
+
+ case SSL3_ST_SW_HELLO_REQ_A:
+ case SSL3_ST_SW_HELLO_REQ_B:
+
+ s->shutdown = 0;
+ dtls1_clear_record_buffer(s);
+ dtls1_start_timer(s);
+ ret = dtls1_send_hello_request(s);
+ if (ret <= 0)
+ goto end;
+ s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->init_num = 0;
+
+ ssl3_init_finished_mac(s);
+ break;
+
+ case SSL3_ST_SW_HELLO_REQ_C:
+ s->state = SSL_ST_OK;
+ break;
+
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ case SSL3_ST_SR_CLNT_HELLO_B:
+ case SSL3_ST_SR_CLNT_HELLO_C:
+
+ s->shutdown = 0;
+ ret = ssl3_get_client_hello(s);
+ if (ret <= 0)
+ goto end;
+ dtls1_stop_timer(s);
+
+ if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
+ s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
+ else
+ s->state = SSL3_ST_SW_SRVR_HELLO_A;
+
+ s->init_num = 0;
+
+ /*
+ * Reflect ClientHello sequence to remain stateless while
+ * listening
+ */
+ if (listen) {
+ memcpy(s->s3->write_sequence, s->s3->read_sequence,
+ sizeof(s->s3->write_sequence));
+ }
+
+ /* If we're just listening, stop here */
+ if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) {
+ ret = 2;
+ s->d1->listen = 0;
+ /*
+ * Set expected sequence numbers to continue the handshake.
+ */
+ s->d1->handshake_read_seq = 2;
+ s->d1->handshake_write_seq = 1;
+ s->d1->next_handshake_write_seq = 1;
+ goto end;
+ }
+
+ break;
+
+ case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
+ case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
+
+ ret = dtls1_send_hello_verify_request(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;
+
+ /* HelloVerifyRequest resets Finished MAC */
+ if (s->version != DTLS1_BAD_VER)
+ ssl3_init_finished_mac(s);
+ break;
+
#ifndef OPENSSL_NO_SCTP
- case DTLS1_SCTP_ST_SR_READ_SOCK:
-
- if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
- {
- s->s3->in_read_app_data=2;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- ret = -1;
- goto end;
- }
-
- s->state=SSL3_ST_SR_FINISHED_A;
- break;
-
- case DTLS1_SCTP_ST_SW_WRITE_SOCK:
- ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
- if (ret < 0) goto end;
-
- if (ret == 0)
- {
- if (s->d1->next_state != SSL_ST_OK)
- {
- s->s3->in_read_app_data=2;
- s->rwstate=SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- ret = -1;
- goto end;
- }
- }
-
- s->state=s->d1->next_state;
- break;
+ case DTLS1_SCTP_ST_SR_READ_SOCK:
+
+ if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state = SSL3_ST_SR_FINISHED_A;
+ break;
+
+ case DTLS1_SCTP_ST_SW_WRITE_SOCK:
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0)
+ goto end;
+
+ if (ret == 0) {
+ if (s->d1->next_state != SSL_ST_OK) {
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+ }
+
+ s->state = s->d1->next_state;
+ break;
#endif
- case SSL3_ST_SW_SRVR_HELLO_A:
- case SSL3_ST_SW_SRVR_HELLO_B:
- s->renegotiate = 2;
- dtls1_start_timer(s);
- ret=dtls1_send_server_hello(s);
- if (ret <= 0) goto end;
+ case SSL3_ST_SW_SRVR_HELLO_A:
+ case SSL3_ST_SW_SRVR_HELLO_B:
+ s->renegotiate = 2;
+ dtls1_start_timer(s);
+ ret = dtls1_send_server_hello(s);
+ if (ret <= 0)
+ goto end;
- if (s->hit)
- {
+ if (s->hit) {
#ifndef OPENSSL_NO_SCTP
- /* Add new shared key for SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
- DTLS1_SCTP_AUTH_LABEL);
-
- SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no
+ * SCTP used.
+ */
+ snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0);
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
#endif
#ifndef OPENSSL_NO_TLSEXT
- if (s->tlsext_ticket_expected)
- s->state=SSL3_ST_SW_SESSION_TICKET_A;
- else
- s->state=SSL3_ST_SW_CHANGE_A;
+ if (s->tlsext_ticket_expected)
+ s->state = SSL3_ST_SW_SESSION_TICKET_A;
+ else
+ s->state = SSL3_ST_SW_CHANGE_A;
#else
- s->state=SSL3_ST_SW_CHANGE_A;
+ s->state = SSL3_ST_SW_CHANGE_A;
#endif
- }
- else
- s->state=SSL3_ST_SW_CERT_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_SW_CERT_A:
- case SSL3_ST_SW_CERT_B:
- /* Check if it is anon DH or normal PSK */
- 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);
- if (ret <= 0) goto end;
+ } else
+ s->state = SSL3_ST_SW_CERT_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CERT_A:
+ case SSL3_ST_SW_CERT_B:
+ /* Check if it is anon DH or normal PSK */
+ 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);
+ if (ret <= 0)
+ goto end;
#ifndef OPENSSL_NO_TLSEXT
- if (s->tlsext_status_expected)
- s->state=SSL3_ST_SW_CERT_STATUS_A;
- else
- s->state=SSL3_ST_SW_KEY_EXCH_A;
- }
- else
- {
- skip = 1;
- s->state=SSL3_ST_SW_KEY_EXCH_A;
- }
+ if (s->tlsext_status_expected)
+ s->state = SSL3_ST_SW_CERT_STATUS_A;
+ else
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
+ } else {
+ skip = 1;
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
+ }
#else
- }
- else
- skip=1;
+ } else
+ skip = 1;
- s->state=SSL3_ST_SW_KEY_EXCH_A;
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
#endif
- s->init_num=0;
- break;
-
- case SSL3_ST_SW_KEY_EXCH_A:
- case SSL3_ST_SW_KEY_EXCH_B:
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- /*
- * clear this, it may get reset by
- * send_server_key_exchange
- */
- s->s3->tmp.use_rsa_tmp=0;
-
- /* only send if a DH key exchange or
- * RSA but we have a sign only certificate */
- if (0
- /* PSK: send ServerKeyExchange if PSK identity
- * hint if provided */
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_KEY_EXCH_A:
+ case SSL3_ST_SW_KEY_EXCH_B:
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * clear this, it may get reset by
+ * send_server_key_exchange
+ */
+ s->s3->tmp.use_rsa_tmp = 0;
+
+ /*
+ * only send if a DH key exchange or RSA but we have a sign only
+ * certificate
+ */
+ if (0
+ /*
+ * PSK: send ServerKeyExchange if PSK identity hint if
+ * provided
+ */
#ifndef OPENSSL_NO_PSK
- || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+ || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
#endif
- || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
- || (alg_k & SSL_kEECDH)
- || ((alg_k & SSL_kRSA)
- && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
- || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
- && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
- )
- )
- )
- )
- {
- dtls1_start_timer(s);
- ret=dtls1_send_server_key_exchange(s);
- if (ret <= 0) goto end;
- }
- else
- skip=1;
-
- s->state=SSL3_ST_SW_CERT_REQ_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_SW_CERT_REQ_A:
- case SSL3_ST_SW_CERT_REQ_B:
- if (/* don't request cert unless asked for it: */
- !(s->verify_mode & SSL_VERIFY_PEER) ||
- /* if SSL_VERIFY_CLIENT_ONCE is set,
- * don't request cert during re-negotiation: */
- ((s->session->peer != NULL) &&
- (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
- /* never request cert in anonymous ciphersuites
- * (see section "Certificate request" in SSL 3 drafts
- * and in RFC 2246): */
- ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
- /* ... except when the application insists on verification
- * (against the specs, but s3_clnt.c accepts this for SSL 3) */
- !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
- /* never request cert in Kerberos ciphersuites */
- (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
- /* With normal PSK Certificates and
- * Certificate Requests are omitted */
- || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
- {
- /* no cert request */
- skip=1;
- s->s3->tmp.cert_request=0;
- s->state=SSL3_ST_SW_SRVR_DONE_A;
+ || (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd))
+ || (alg_k & SSL_kEECDH)
+ || ((alg_k & SSL_kRSA)
+ && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
+ || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
+ && EVP_PKEY_size(s->cert->pkeys
+ [SSL_PKEY_RSA_ENC].privatekey) *
+ 8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
+ )
+ )
+ )
+ ) {
+ dtls1_start_timer(s);
+ ret = dtls1_send_server_key_exchange(s);
+ if (ret <= 0)
+ goto end;
+ } else
+ skip = 1;
+
+ s->state = SSL3_ST_SW_CERT_REQ_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CERT_REQ_A:
+ case SSL3_ST_SW_CERT_REQ_B:
+ if ( /* don't request cert unless asked for it: */
+ !(s->verify_mode & SSL_VERIFY_PEER) ||
+ /*
+ * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
+ * during re-negotiation:
+ */
+ ((s->session->peer != NULL) &&
+ (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
+ /*
+ * never request cert in anonymous ciphersuites (see
+ * section "Certificate request" in SSL 3 drafts and in
+ * RFC 2246):
+ */
+ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+ /*
+ * ... except when the application insists on
+ * verification (against the specs, but s3_clnt.c accepts
+ * this for SSL 3)
+ */
+ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+ /*
+ * never request cert in Kerberos ciphersuites
+ */
+ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
+ /*
+ * With normal PSK Certificates and Certificate Requests
+ * are omitted
+ */
+ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ /* no cert request */
+ skip = 1;
+ s->s3->tmp.cert_request = 0;
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
- s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
+ s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
#endif
- }
- else
- {
- s->s3->tmp.cert_request=1;
- dtls1_start_timer(s);
- ret=dtls1_send_certificate_request(s);
- if (ret <= 0) goto end;
+ } else {
+ s->s3->tmp.cert_request = 1;
+ dtls1_start_timer(s);
+ ret = dtls1_send_certificate_request(s);
+ if (ret <= 0)
+ goto end;
#ifndef NETSCAPE_HANG_BUG
- s->state=SSL3_ST_SW_SRVR_DONE_A;
-#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
- s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
- }
-#endif
+ s->state = SSL3_ST_SW_SRVR_DONE_A;
+# ifndef OPENSSL_NO_SCTP
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
+ s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+# endif
#else
- s->state=SSL3_ST_SW_FLUSH;
- s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
-#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = s->s3->tmp.next_state;
- s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
- }
-#endif
+ s->state = SSL3_ST_SW_FLUSH;
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+# ifndef OPENSSL_NO_SCTP
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+# endif
#endif
- s->init_num=0;
- }
- break;
-
- case SSL3_ST_SW_SRVR_DONE_A:
- case SSL3_ST_SW_SRVR_DONE_B:
- dtls1_start_timer(s);
- ret=dtls1_send_server_done(s);
- if (ret <= 0) goto end;
- s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
- s->state=SSL3_ST_SW_FLUSH;
- s->init_num=0;
- break;
-
- case SSL3_ST_SW_FLUSH:
- s->rwstate=SSL_WRITING;
- if (BIO_flush(s->wbio) <= 0)
- {
- /* If the write error was fatal, stop trying */
- if (!BIO_should_retry(s->wbio))
- {
- s->rwstate=SSL_NOTHING;
- s->state=s->s3->tmp.next_state;
- }
-
- ret= -1;
- goto end;
- }
- s->rwstate=SSL_NOTHING;
- s->state=s->s3->tmp.next_state;
- break;
-
- 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;
- }
- break;
-
- case SSL3_ST_SR_KEY_EXCH_A:
- case SSL3_ST_SR_KEY_EXCH_B:
- ret=ssl3_get_client_key_exchange(s);
- if (ret <= 0) goto end;
+ s->init_num = 0;
+ }
+ break;
+
+ case SSL3_ST_SW_SRVR_DONE_A:
+ case SSL3_ST_SW_SRVR_DONE_B:
+ dtls1_start_timer(s);
+ ret = dtls1_send_server_done(s);
+ if (ret <= 0)
+ goto end;
+ s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
+ s->state = SSL3_ST_SW_FLUSH;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_FLUSH:
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ /*
+ * If the write error was fatal, stop trying
+ */
+ if (!BIO_should_retry(s->wbio)) {
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ }
+
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
+
+ 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;
+ }
+ break;
+
+ case SSL3_ST_SR_KEY_EXCH_A:
+ case SSL3_ST_SR_KEY_EXCH_B:
+ ret = ssl3_get_client_key_exchange(s);
+ if (ret <= 0)
+ goto end;
#ifndef OPENSSL_NO_SCTP
- /* Add new shared key for SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
- DTLS1_SCTP_AUTH_LABEL);
-
- SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0);
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
#endif
- s->state=SSL3_ST_SR_CERT_VRFY_A;
- s->init_num=0;
-
- if (ret == 2)
- {
- /* For the ECDH ciphersuites when
- * the client sends its ECDH pub key in
- * a certificate, the CertificateVerify
- * message is not sent.
- */
- s->state=SSL3_ST_SR_FINISHED_A;
- s->init_num = 0;
- }
- else
- {
- s->state=SSL3_ST_SR_CERT_VRFY_A;
- s->init_num=0;
-
- /* We need to get hashes here so if there is
- * a client cert, it can be verified */
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_md5,
- &(s->s3->tmp.cert_verify_md[0]));
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_sha1,
- &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
- }
- break;
-
- case SSL3_ST_SR_CERT_VRFY_A:
- case SSL3_ST_SR_CERT_VRFY_B:
- /*
- * This *should* be the first time we enable CCS, but be
- * extra careful about surrounding code changes. We need
- * to set this here because we don't know if we're
- * expecting a CertificateVerify or not.
- */
- if (!s->s3->change_cipher_spec)
- s->d1->change_cipher_spec_ok = 1;
- /* we should decide if we expected this one */
- ret=ssl3_get_cert_verify(s);
- if (ret <= 0) goto end;
+ s->state = SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num = 0;
+
+ if (ret == 2) {
+ /*
+ * For the ECDH ciphersuites when the client sends its ECDH
+ * pub key in a certificate, the CertificateVerify message is
+ * not sent.
+ */
+ s->state = SSL3_ST_SR_FINISHED_A;
+ s->init_num = 0;
+ } else {
+ s->state = SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num = 0;
+
+ /*
+ * We need to get hashes here so if there is a client cert,
+ * it can be verified
+ */
+ s->method->ssl3_enc->cert_verify_mac(s,
+ NID_md5,
+ &(s->s3->
+ tmp.cert_verify_md
+ [0]));
+ s->method->ssl3_enc->cert_verify_mac(s, NID_sha1,
+ &(s->s3->
+ tmp.cert_verify_md
+ [MD5_DIGEST_LENGTH]));
+ }
+ break;
+
+ case SSL3_ST_SR_CERT_VRFY_A:
+ case SSL3_ST_SR_CERT_VRFY_B:
+ /*
+ * This *should* be the first time we enable CCS, but be
+ * extra careful about surrounding code changes. We need
+ * to set this here because we don't know if we're
+ * expecting a CertificateVerify or not.
+ */
+ if (!s->s3->change_cipher_spec)
+ s->d1->change_cipher_spec_ok = 1;
+ /* we should decide if we expected this one */
+ ret = ssl3_get_cert_verify(s);
+ if (ret <= 0)
+ goto end;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
- state == SSL_ST_RENEGOTIATE)
- s->state=DTLS1_SCTP_ST_SR_READ_SOCK;
- else
-#endif
- s->state=SSL3_ST_SR_FINISHED_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_SR_FINISHED_A:
- case SSL3_ST_SR_FINISHED_B:
- /*
- * Enable CCS for resumed handshakes.
- * In a full handshake, we end up here through
- * SSL3_ST_SR_CERT_VRFY_B, so change_cipher_spec_ok was
- * already set. Receiving a CCS clears the flag, so make
- * sure not to re-enable it to ban duplicates.
- * s->s3->change_cipher_spec is set when a CCS is
- * processed in d1_pkt.c, and remains set until
- * the client's Finished message is read.
- */
- if (!s->s3->change_cipher_spec)
- s->d1->change_cipher_spec_ok = 1;
- ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
- SSL3_ST_SR_FINISHED_B);
- if (ret <= 0) goto end;
- dtls1_stop_timer(s);
- if (s->hit)
- s->state=SSL_ST_OK;
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ state == SSL_ST_RENEGOTIATE)
+ s->state = DTLS1_SCTP_ST_SR_READ_SOCK;
+ else
+#endif
+ s->state = SSL3_ST_SR_FINISHED_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SR_FINISHED_A:
+ case SSL3_ST_SR_FINISHED_B:
+ /*
+ * Enable CCS for resumed handshakes.
+ * In a full handshake, we end up here through
+ * SSL3_ST_SR_CERT_VRFY_B, so change_cipher_spec_ok was
+ * already set. Receiving a CCS clears the flag, so make
+ * sure not to re-enable it to ban duplicates.
+ * s->s3->change_cipher_spec is set when a CCS is
+ * processed in d1_pkt.c, and remains set until
+ * the client's Finished message is read.
+ */
+ if (!s->s3->change_cipher_spec)
+ s->d1->change_cipher_spec_ok = 1;
+ ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A,
+ SSL3_ST_SR_FINISHED_B);
+ if (ret <= 0)
+ goto end;
+ dtls1_stop_timer(s);
+ if (s->hit)
+ s->state = SSL_ST_OK;
#ifndef OPENSSL_NO_TLSEXT
- else if (s->tlsext_ticket_expected)
- s->state=SSL3_ST_SW_SESSION_TICKET_A;
+ else if (s->tlsext_ticket_expected)
+ s->state = SSL3_ST_SW_SESSION_TICKET_A;
#endif
- else
- s->state=SSL3_ST_SW_CHANGE_A;
- s->init_num=0;
- break;
+ else
+ s->state = SSL3_ST_SW_CHANGE_A;
+ s->init_num = 0;
+ break;
#ifndef OPENSSL_NO_TLSEXT
- case SSL3_ST_SW_SESSION_TICKET_A:
- case SSL3_ST_SW_SESSION_TICKET_B:
- ret=dtls1_send_newsession_ticket(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_SW_CHANGE_A;
- s->init_num=0;
- break;
-
- case SSL3_ST_SW_CERT_STATUS_A:
- case SSL3_ST_SW_CERT_STATUS_B:
- ret=ssl3_send_cert_status(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_SW_KEY_EXCH_A;
- s->init_num=0;
- break;
+ case SSL3_ST_SW_SESSION_TICKET_A:
+ case SSL3_ST_SW_SESSION_TICKET_B:
+ ret = dtls1_send_newsession_ticket(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_SW_CHANGE_A;
+ s->init_num = 0;
+ break;
+
+ case SSL3_ST_SW_CERT_STATUS_A:
+ case SSL3_ST_SW_CERT_STATUS_B:
+ ret = ssl3_send_cert_status(s);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_SW_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
#endif
- case SSL3_ST_SW_CHANGE_A:
- case SSL3_ST_SW_CHANGE_B:
+ case SSL3_ST_SW_CHANGE_A:
+ case SSL3_ST_SW_CHANGE_B:
- s->session->cipher=s->s3->tmp.new_cipher;
- if (!s->method->ssl3_enc->setup_key_block(s))
- { ret= -1; goto end; }
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
- ret=dtls1_send_change_cipher_spec(s,
- SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
+ ret = dtls1_send_change_cipher_spec(s,
+ SSL3_ST_SW_CHANGE_A,
+ SSL3_ST_SW_CHANGE_B);
- if (ret <= 0) goto end;
+ if (ret <= 0)
+ goto end;
#ifndef OPENSSL_NO_SCTP
- if (!s->hit)
- {
- /* Change to new shared key of SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
- }
+ if (!s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
#endif
- s->state=SSL3_ST_SW_FINISHED_A;
- s->init_num=0;
-
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CHANGE_CIPHER_SERVER_WRITE))
- {
- ret= -1;
- goto end;
- }
-
- dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
- break;
-
- 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);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_SW_FLUSH;
- if (s->hit)
- {
- s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+ s->state = SSL3_ST_SW_FINISHED_A;
+ s->init_num = 0;
+
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_SERVER_WRITE))
+ {
+ ret = -1;
+ goto end;
+ }
+
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ 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);
+ if (ret <= 0)
+ goto end;
+ s->state = SSL3_ST_SW_FLUSH;
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A;
#ifndef OPENSSL_NO_SCTP
- /* Change to new shared key of SCTP-Auth,
- * will be ignored if no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
#endif
- }
- else
- {
- s->s3->tmp.next_state=SSL_ST_OK;
+ } else {
+ s->s3->tmp.next_state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
- {
- s->d1->next_state = s->s3->tmp.next_state;
- s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
- }
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
#endif
- }
- s->init_num=0;
- break;
+ }
+ s->init_num = 0;
+ break;
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(s);
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
#if 0
- BUF_MEM_free(s->init_buf);
- s->init_buf=NULL;
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
#endif
- /* remove buffering on output */
- ssl_free_wbio_buffer(s);
-
- s->init_num=0;
-
- if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
- {
- s->renegotiate=0;
- s->new_session=0;
-
- ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
-
- s->ctx->stats.sess_accept_good++;
- /* s->server=1; */
- s->handshake_func=dtls1_accept;
-
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
- }
-
- ret = 1;
-
- /* done handshaking, next message is client hello */
- s->d1->handshake_read_seq = 0;
- /* next message is server hello */
- s->d1->handshake_write_seq = 0;
- s->d1->next_handshake_write_seq = 0;
- goto end;
- /* break; */
-
- default:
- SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE);
- ret= -1;
- goto end;
- /* break; */
- }
-
- if (!s->s3->tmp.reuse_message && !skip)
- {
- if (s->debug)
- {
- if ((ret=BIO_flush(s->wbio)) <= 0)
- goto end;
- }
-
-
- if ((cb != NULL) && (s->state != state))
- {
- new_state=s->state;
- s->state=state;
- cb(s,SSL_CB_ACCEPT_LOOP,1);
- s->state=new_state;
- }
- }
- skip=0;
- }
-end:
- /* BIO_flush(s->wbio); */
-
- s->in_handshake--;
+ /* remove buffering on output */
+ ssl_free_wbio_buffer(s);
+
+ s->init_num = 0;
+
+ if (s->renegotiate == 2) { /* skipped if we just sent a
+ * HelloRequest */
+ s->renegotiate = 0;
+ s->new_session = 0;
+
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+
+ s->ctx->stats.sess_accept_good++;
+ /* s->server=1; */
+ s->handshake_func = dtls1_accept;
+
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
+
+ ret = 1;
+
+ /* done handshaking, next message is client hello */
+ s->d1->handshake_read_seq = 0;
+ /* next message is server hello */
+ s->d1->handshake_write_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ goto end;
+ /* break; */
+
+ default:
+ SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ /* break; */
+ }
+
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if (s->debug) {
+ if ((ret = BIO_flush(s->wbio)) <= 0)
+ goto end;
+ }
+
+ if ((cb != NULL) && (s->state != state)) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_ACCEPT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+ end:
+ /* BIO_flush(s->wbio); */
+
+ s->in_handshake--;
#ifndef OPENSSL_NO_SCTP
- /* Notify SCTP BIO socket to leave handshake
- * mode and prevent stream identifier other
- * than 0. Will be ignored if no SCTP is used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL);
+ /*
+ * Notify SCTP BIO socket to leave handshake mode and prevent stream
+ * identifier other than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ s->in_handshake, NULL);
#endif
- if (cb != NULL)
- cb(s,SSL_CB_ACCEPT_EXIT,ret);
- return(ret);
- }
+ if (cb != NULL)
+ cb(s, SSL_CB_ACCEPT_EXIT, ret);
+ return (ret);
+}
int dtls1_send_hello_request(SSL *s)
- {
- unsigned char *p;
+{
+ 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);
+ 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;
+ 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 */
- }
+ /*
+ * 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));
- }
+ /* 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;
- unsigned char *msg, *buf, *p;
-
- if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A)
- {
- buf = (unsigned char *)s->init_buf->data;
-
- msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
- *(p++) = s->version >> 8;
- *(p++) = s->version & 0xFF;
-
- if (s->ctx->app_gen_cookie_cb == NULL ||
- s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
- &(s->d1->cookie_len)) == 0)
- {
- SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- *(p++) = (unsigned char) s->d1->cookie_len;
- memcpy(p, s->d1->cookie, s->d1->cookie_len);
- p += s->d1->cookie_len;
- msg_len = p - msg;
-
- dtls1_set_message_header(s, buf,
- DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0, msg_len);
-
- s->state=DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B;
- /* number of bytes to write */
- s->init_num=p-buf;
- s->init_off=0;
- }
-
- /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
- return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
- }
+{
+ unsigned int msg_len;
+ unsigned char *msg, *buf, *p;
+
+ if (s->state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) {
+ buf = (unsigned char *)s->init_buf->data;
+
+ msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
+ *(p++) = s->version >> 8;
+ *(p++) = s->version & 0xFF;
+
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
+ &(s->d1->cookie_len)) == 0) {
+ SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ *(p++) = (unsigned char)s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ msg_len = p - msg;
+
+ dtls1_set_message_header(s, buf,
+ DTLS1_MT_HELLO_VERIFY_REQUEST, msg_len, 0,
+ msg_len);
+
+ s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B;
+ /* number of bytes to write */
+ s->init_num = p - buf;
+ s->init_off = 0;
+ }
+
+ /* 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 */
+{
+ 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;
+ *(p++) = 0;
#else
- if (s->s3->tmp.new_compression == NULL)
- *(p++)=0;
- else
- *(p++)=s->s3->tmp.new_compression->id;
+ 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;
- }
+ 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;
+ /* do the header */
+ l = (p - d);
+ d = buf;
- d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l);
+ 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;
+ 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);
- }
+ /* 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));
- }
+ /* SSL3_ST_SW_SRVR_HELLO_B */
+ return (dtls1_do_write(s, SSL3_RT_HANDSHAKE));
+}
int dtls1_send_server_done(SSL *s)
- {
- unsigned char *p;
+{
+ unsigned char *p;
- if (s->state == SSL3_ST_SW_SRVR_DONE_A)
- {
- p=(unsigned char *)s->init_buf->data;
+ 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);
+ /* 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;
+ 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);
- }
+ /* 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));
- }
+ /* 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;
+ 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;
+ 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;
+ 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;
+ 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
+ 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
+ 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 */
+ 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];
- }
+ 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;
- }
+ 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);
- }
+ 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. */
+ /* 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
+ 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
+ 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
+ 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:
+ {
+ /* 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);
+ if (encodedPoint != NULL)
+ OPENSSL_free(encodedPoint);
+ BN_CTX_free(bn_ctx);
#endif
- EVP_MD_CTX_cleanup(&md_ctx);
- return(-1);
- }
+ 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;
+{
+ 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;
+ 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);
+ /* 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);
+ /* buffer the message to handle re-xmits */
+ dtls1_buffer_message(s, 0);
- s->state = SSL3_ST_SW_CERT_REQ_B;
- }
+ 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);
- }
+ /* 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));
- }
+{
+ 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));
- }
+{
+ 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 338575268f9e..8deb299a7c85 100644
--- a/ssl/dtls1.h
+++ b/ssl/dtls1.h
@@ -1,7 +1,7 @@
/* ssl/dtls1.h */
-/*
+/*
* DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
@@ -11,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -58,237 +58,209 @@
*/
#ifndef HEADER_DTLS1_H
-#define HEADER_DTLS1_H
-
-#include <openssl/buffer.h>
-#include <openssl/pqueue.h>
-#ifdef OPENSSL_SYS_VMS
-#include <resource.h>
-#include <sys/timeb.h>
-#endif
-#ifdef OPENSSL_SYS_WIN32
+# define HEADER_DTLS1_H
+
+# include <openssl/buffer.h>
+# include <openssl/pqueue.h>
+# ifdef OPENSSL_SYS_VMS
+# include <resource.h>
+# include <sys/timeb.h>
+# endif
+# ifdef OPENSSL_SYS_WIN32
/* Needed for struct timeval */
-#include <winsock.h>
-#elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
-#include <sys/timeval.h>
-#else
-#if defined(OPENSSL_SYS_VXWORKS)
-#include <sys/times.h>
-#else
-#include <sys/time.h>
-#endif
-#endif
+# include <winsock.h>
+# elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
+# include <sys/timeval.h>
+# else
+# if defined(OPENSSL_SYS_VXWORKS)
+# include <sys/times.h>
+# else
+# include <sys/time.h>
+# endif
+# endif
#ifdef __cplusplus
extern "C" {
#endif
-#define DTLS1_VERSION 0xFEFF
-#define DTLS_MAX_VERSION DTLS1_VERSION
+# define DTLS1_VERSION 0xFEFF
+# define DTLS_MAX_VERSION DTLS1_VERSION
+# define DTLS1_VERSION_MAJOR 0xFE
-#define DTLS1_BAD_VER 0x0100
+# define DTLS1_BAD_VER 0x0100
-#if 0
+# if 0
/* this alert description is not specified anywhere... */
-#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
-#endif
+# define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
+# endif
/* lengths of messages */
-#define DTLS1_COOKIE_LENGTH 256
+# define DTLS1_COOKIE_LENGTH 256
-#define DTLS1_RT_HEADER_LENGTH 13
+# define DTLS1_RT_HEADER_LENGTH 13
-#define DTLS1_HM_HEADER_LENGTH 12
+# define DTLS1_HM_HEADER_LENGTH 12
-#define DTLS1_HM_BAD_FRAGMENT -2
-#define DTLS1_HM_FRAGMENT_RETRY -3
+# define DTLS1_HM_BAD_FRAGMENT -2
+# define DTLS1_HM_FRAGMENT_RETRY -3
-#define DTLS1_CCS_HEADER_LENGTH 1
+# define DTLS1_CCS_HEADER_LENGTH 1
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-#define DTLS1_AL_HEADER_LENGTH 7
-#else
-#define DTLS1_AL_HEADER_LENGTH 2
-#endif
+# ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+# define DTLS1_AL_HEADER_LENGTH 7
+# else
+# define DTLS1_AL_HEADER_LENGTH 2
+# endif
-#ifndef OPENSSL_NO_SSL_INTERN
+# ifndef OPENSSL_NO_SSL_INTERN
-#ifndef OPENSSL_NO_SCTP
-#define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
-#endif
+# ifndef OPENSSL_NO_SCTP
+# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
+# endif
/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
-#define DTLS1_MAX_MTU_OVERHEAD 48
-
-typedef struct dtls1_bitmap_st
- {
- unsigned long map; /* track 32 packets on 32-bit systems
- and 64 - on 64-bit systems */
- unsigned char max_seq_num[8]; /* max record number seen so far,
- 64-bit value in big-endian
- encoding */
- } DTLS1_BITMAP;
-
-struct dtls1_retransmit_state
- {
- EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
- EVP_MD_CTX *write_hash; /* used for mac generation */
-#ifndef OPENSSL_NO_COMP
- COMP_CTX *compress; /* compression */
-#else
- char *compress;
-#endif
- SSL_SESSION *session;
- unsigned short epoch;
- };
-
-struct hm_header_st
- {
- unsigned char type;
- unsigned long msg_len;
- unsigned short seq;
- unsigned long frag_off;
- unsigned long frag_len;
- unsigned int is_ccs;
- struct dtls1_retransmit_state saved_retransmit_state;
- };
-
-struct ccs_header_st
- {
- unsigned char type;
- unsigned short seq;
- };
-
-struct dtls1_timeout_st
- {
- /* Number of read timeouts so far */
- unsigned int read_timeouts;
-
- /* Number of write timeouts so far */
- unsigned int write_timeouts;
-
- /* Number of alerts received so far */
- unsigned int num_alerts;
- };
-
-typedef struct record_pqueue_st
- {
- unsigned short epoch;
- pqueue q;
- } record_pqueue;
-
-typedef struct hm_fragment_st
- {
- struct hm_header_st msg_header;
- unsigned char *fragment;
- unsigned char *reassembly;
- } hm_fragment;
-
-typedef struct dtls1_state_st
- {
- unsigned int send_cookie;
- unsigned char cookie[DTLS1_COOKIE_LENGTH];
- unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
- unsigned int cookie_len;
-
- /*
- * The current data and handshake epoch. This is initially
- * undefined, and starts at zero once the initial handshake is
- * completed
- */
- unsigned short r_epoch;
- unsigned short w_epoch;
-
- /* records being received in the current epoch */
- DTLS1_BITMAP bitmap;
-
- /* renegotiation starts a new set of sequence numbers */
- DTLS1_BITMAP next_bitmap;
-
- /* handshake message numbers */
- unsigned short handshake_write_seq;
- unsigned short next_handshake_write_seq;
-
- unsigned short handshake_read_seq;
-
- /* save last sequence number for retransmissions */
- unsigned char last_write_sequence[8];
-
- /* Received handshake records (processed and unprocessed) */
- record_pqueue unprocessed_rcds;
- record_pqueue processed_rcds;
-
- /* Buffered handshake messages */
- pqueue buffered_messages;
-
- /* Buffered (sent) handshake records */
- pqueue sent_messages;
-
- /* Buffered application records.
- * Only for records between CCS and Finished
- * to prevent either protocol violation or
- * unnecessary message loss.
- */
- record_pqueue buffered_app_data;
-
- /* Is set when listening for new connections with dtls1_listen() */
- unsigned int listen;
-
- unsigned int link_mtu; /* max on-the-wire DTLS packet size */
- unsigned int mtu; /* max DTLS packet size */
-
- struct hm_header_st w_msg_hdr;
- struct hm_header_st r_msg_hdr;
-
- struct dtls1_timeout_st timeout;
-
- /* Indicates when the last handshake msg or heartbeat sent will timeout */
- struct timeval next_timeout;
-
- /* Timeout duration */
- unsigned short timeout_duration;
-
- /* storage for Alert/Handshake protocol data received but not
- * yet processed by ssl3_read_bytes: */
- unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
- unsigned int alert_fragment_len;
- unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
- unsigned int handshake_fragment_len;
-
- unsigned int retransmitting;
- /*
- * Set when the handshake is ready to process peer's ChangeCipherSpec message.
- * Cleared after the message has been processed.
- */
- unsigned int change_cipher_spec_ok;
-
-#ifndef OPENSSL_NO_SCTP
- /* used when SSL_ST_XX_FLUSH is entered */
- int next_state;
-
- int shutdown_received;
-#endif
-
- } DTLS1_STATE;
-
-typedef struct dtls1_record_data_st
- {
- unsigned char *packet;
- unsigned int packet_length;
- SSL3_BUFFER rbuf;
- SSL3_RECORD rrec;
-#ifndef OPENSSL_NO_SCTP
- struct bio_dgram_sctp_rcvinfo recordinfo;
-#endif
- } DTLS1_RECORD_DATA;
-
-#endif
+# define DTLS1_MAX_MTU_OVERHEAD 48
+
+typedef struct dtls1_bitmap_st {
+ unsigned long map; /* track 32 packets on 32-bit systems and 64
+ * - on 64-bit systems */
+ unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit
+ * value in big-endian encoding */
+} DTLS1_BITMAP;
+
+struct dtls1_retransmit_state {
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ EVP_MD_CTX *write_hash; /* used for mac generation */
+# ifndef OPENSSL_NO_COMP
+ COMP_CTX *compress; /* compression */
+# else
+ char *compress;
+# endif
+ SSL_SESSION *session;
+ unsigned short epoch;
+};
+
+struct hm_header_st {
+ unsigned char type;
+ unsigned long msg_len;
+ unsigned short seq;
+ unsigned long frag_off;
+ unsigned long frag_len;
+ unsigned int is_ccs;
+ struct dtls1_retransmit_state saved_retransmit_state;
+};
+
+struct ccs_header_st {
+ unsigned char type;
+ unsigned short seq;
+};
+
+struct dtls1_timeout_st {
+ /* Number of read timeouts so far */
+ unsigned int read_timeouts;
+ /* Number of write timeouts so far */
+ unsigned int write_timeouts;
+ /* Number of alerts received so far */
+ unsigned int num_alerts;
+};
+
+typedef struct record_pqueue_st {
+ unsigned short epoch;
+ pqueue q;
+} record_pqueue;
+
+typedef struct hm_fragment_st {
+ struct hm_header_st msg_header;
+ unsigned char *fragment;
+ unsigned char *reassembly;
+} hm_fragment;
+
+typedef struct dtls1_state_st {
+ unsigned int send_cookie;
+ unsigned char cookie[DTLS1_COOKIE_LENGTH];
+ unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+ unsigned int cookie_len;
+ /*
+ * The current data and handshake epoch. This is initially
+ * undefined, and starts at zero once the initial handshake is
+ * completed
+ */
+ unsigned short r_epoch;
+ unsigned short w_epoch;
+ /* records being received in the current epoch */
+ DTLS1_BITMAP bitmap;
+ /* renegotiation starts a new set of sequence numbers */
+ DTLS1_BITMAP next_bitmap;
+ /* handshake message numbers */
+ unsigned short handshake_write_seq;
+ unsigned short next_handshake_write_seq;
+ unsigned short handshake_read_seq;
+ /* save last sequence number for retransmissions */
+ unsigned char last_write_sequence[8];
+ /* Received handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+ /* Buffered handshake messages */
+ pqueue buffered_messages;
+ /* Buffered (sent) handshake records */
+ pqueue sent_messages;
+ /*
+ * Buffered application records. Only for records between CCS and
+ * Finished to prevent either protocol violation or unnecessary message
+ * loss.
+ */
+ record_pqueue buffered_app_data;
+ /* Is set when listening for new connections with dtls1_listen() */
+ unsigned int listen;
+ unsigned int link_mtu; /* max on-the-wire DTLS packet size */
+ unsigned int mtu; /* max DTLS packet size */
+ struct hm_header_st w_msg_hdr;
+ struct hm_header_st r_msg_hdr;
+ struct dtls1_timeout_st timeout;
+ /*
+ * Indicates when the last handshake msg or heartbeat sent will timeout
+ */
+ struct timeval next_timeout;
+ /* Timeout duration */
+ unsigned short timeout_duration;
+ /*
+ * storage for Alert/Handshake protocol data received but not yet
+ * processed by ssl3_read_bytes:
+ */
+ unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+ unsigned int handshake_fragment_len;
+ unsigned int retransmitting;
+ /*
+ * Set when the handshake is ready to process peer's ChangeCipherSpec message.
+ * Cleared after the message has been processed.
+ */
+ unsigned int change_cipher_spec_ok;
+# ifndef OPENSSL_NO_SCTP
+ /* used when SSL_ST_XX_FLUSH is entered */
+ int next_state;
+ int shutdown_received;
+# endif
+} DTLS1_STATE;
+
+typedef struct dtls1_record_data_st {
+ unsigned char *packet;
+ unsigned int packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+# ifndef OPENSSL_NO_SCTP
+ struct bio_dgram_sctp_rcvinfo recordinfo;
+# endif
+} DTLS1_RECORD_DATA;
+
+# endif
/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
-#define DTLS1_TMO_READ_COUNT 2
-#define DTLS1_TMO_WRITE_COUNT 2
+# define DTLS1_TMO_READ_COUNT 2
+# define DTLS1_TMO_WRITE_COUNT 2
-#define DTLS1_TMO_ALERT_COUNT 12
+# define DTLS1_TMO_ALERT_COUNT 12
#ifdef __cplusplus
}
diff --git a/ssl/heartbeat_test.c b/ssl/heartbeat_test.c
index de9d39761ef8..3cec8b163fae 100644
--- a/ssl/heartbeat_test.c
+++ b/ssl/heartbeat_test.c
@@ -1,5 +1,5 @@
/* test/heartbeat_test.c */
-/*
+/*-
* Unit test for TLS heartbeats.
*
* Acts as a regression test against the Heartbleed bug (CVE-2014-0160).
@@ -51,416 +51,422 @@
#if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST)
/* As per https://tools.ietf.org/html/rfc6520#section-4 */
-#define MIN_PADDING_SIZE 16
+# define MIN_PADDING_SIZE 16
/* Maximum number of payload characters to print as test output */
-#define MAX_PRINTABLE_CHARACTERS 1024
-
-typedef struct heartbeat_test_fixture
- {
- SSL_CTX *ctx;
- SSL *s;
- const char* test_case_name;
- int (*process_heartbeat)(SSL* s);
- unsigned char* payload;
- int sent_payload_len;
- int expected_return_value;
- int return_payload_offset;
- int expected_payload_len;
- const char* expected_return_payload;
- } HEARTBEAT_TEST_FIXTURE;
-
-static HEARTBEAT_TEST_FIXTURE set_up(const char* const test_case_name,
- const SSL_METHOD* meth)
- {
- HEARTBEAT_TEST_FIXTURE fixture;
- int setup_ok = 1;
- memset(&fixture, 0, sizeof(fixture));
- fixture.test_case_name = test_case_name;
-
- fixture.ctx = SSL_CTX_new(meth);
- if (!fixture.ctx)
- {
- fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n",
- test_case_name);
- setup_ok = 0;
- goto fail;
- }
-
- fixture.s = SSL_new(fixture.ctx);
- if (!fixture.s)
- {
- fprintf(stderr, "Failed to allocate SSL for test: %s\n", test_case_name);
- setup_ok = 0;
- goto fail;
- }
-
- if (!ssl_init_wbio_buffer(fixture.s, 1))
- {
- fprintf(stderr, "Failed to set up wbio buffer for test: %s\n",
- test_case_name);
- setup_ok = 0;
- goto fail;
- }
-
- if (!ssl3_setup_buffers(fixture.s))
- {
- fprintf(stderr, "Failed to setup buffers for test: %s\n",
- test_case_name);
- setup_ok = 0;
- goto fail;
- }
-
- /* Clear the memory for the return buffer, since this isn't automatically
- * zeroed in opt mode and will cause spurious test failures that will change
- * with each execution.
- */
- memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len);
-
- fail:
- if (!setup_ok)
- {
- ERR_print_errors_fp(stderr);
- exit(EXIT_FAILURE);
- }
- return fixture;
- }
-
-static HEARTBEAT_TEST_FIXTURE set_up_dtls(const char* const test_case_name)
- {
- HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
- DTLSv1_server_method());
- fixture.process_heartbeat = dtls1_process_heartbeat;
-
- /* As per dtls1_get_record(), skipping the following from the beginning of
- * the returned heartbeat message:
- * type-1 byte; version-2 bytes; sequence number-8 bytes; length-2 bytes
- *
- * And then skipping the 1-byte type encoded by process_heartbeat for
- * a total of 14 bytes, at which point we can grab the length and the
- * payload we seek.
- */
- fixture.return_payload_offset = 14;
- return fixture;
- }
+# define MAX_PRINTABLE_CHARACTERS 1024
+
+typedef struct heartbeat_test_fixture {
+ SSL_CTX *ctx;
+ SSL *s;
+ const char *test_case_name;
+ int (*process_heartbeat) (SSL *s);
+ unsigned char *payload;
+ int sent_payload_len;
+ int expected_return_value;
+ int return_payload_offset;
+ int expected_payload_len;
+ const char *expected_return_payload;
+} HEARTBEAT_TEST_FIXTURE;
+
+static HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name,
+ const SSL_METHOD *meth)
+{
+ HEARTBEAT_TEST_FIXTURE fixture;
+ int setup_ok = 1;
+ memset(&fixture, 0, sizeof(fixture));
+ fixture.test_case_name = test_case_name;
+
+ fixture.ctx = SSL_CTX_new(meth);
+ if (!fixture.ctx) {
+ fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n",
+ test_case_name);
+ setup_ok = 0;
+ goto fail;
+ }
+
+ fixture.s = SSL_new(fixture.ctx);
+ if (!fixture.s) {
+ fprintf(stderr, "Failed to allocate SSL for test: %s\n",
+ test_case_name);
+ setup_ok = 0;
+ goto fail;
+ }
+
+ if (!ssl_init_wbio_buffer(fixture.s, 1)) {
+ fprintf(stderr, "Failed to set up wbio buffer for test: %s\n",
+ test_case_name);
+ setup_ok = 0;
+ goto fail;
+ }
+
+ if (!ssl3_setup_buffers(fixture.s)) {
+ fprintf(stderr, "Failed to setup buffers for test: %s\n",
+ test_case_name);
+ setup_ok = 0;
+ goto fail;
+ }
+
+ /*
+ * Clear the memory for the return buffer, since this isn't automatically
+ * zeroed in opt mode and will cause spurious test failures that will
+ * change with each execution.
+ */
+ memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len);
+
+ fail:
+ if (!setup_ok) {
+ ERR_print_errors_fp(stderr);
+ exit(EXIT_FAILURE);
+ }
+ return fixture;
+}
+
+static HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name)
+{
+ HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
+ DTLSv1_server_method());
+ fixture.process_heartbeat = dtls1_process_heartbeat;
+
+ /*
+ * As per dtls1_get_record(), skipping the following from the beginning
+ * of the returned heartbeat message: type-1 byte; version-2 bytes;
+ * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte
+ * type encoded by process_heartbeat for a total of 14 bytes, at which
+ * point we can grab the length and the payload we seek.
+ */
+ fixture.return_payload_offset = 14;
+ return fixture;
+}
/* Needed by ssl3_write_bytes() */
-static int dummy_handshake(SSL* s)
- {
- return 1;
- }
-
-static HEARTBEAT_TEST_FIXTURE set_up_tls(const char* const test_case_name)
- {
- HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
- TLSv1_server_method());
- fixture.process_heartbeat = tls1_process_heartbeat;
- fixture.s->handshake_func = dummy_handshake;
-
- /* As per do_ssl3_write(), skipping the following from the beginning of
- * the returned heartbeat message:
- * type-1 byte; version-2 bytes; length-2 bytes
- *
- * And then skipping the 1-byte type encoded by process_heartbeat for
- * a total of 6 bytes, at which point we can grab the length and the payload
- * we seek.
- */
- fixture.return_payload_offset = 6;
- return fixture;
- }
+static int dummy_handshake(SSL *s)
+{
+ return 1;
+}
+
+static HEARTBEAT_TEST_FIXTURE set_up_tls(const char *const test_case_name)
+{
+ HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
+ TLSv1_server_method());
+ fixture.process_heartbeat = tls1_process_heartbeat;
+ fixture.s->handshake_func = dummy_handshake;
+
+ /*
+ * As per do_ssl3_write(), skipping the following from the beginning of
+ * the returned heartbeat message: type-1 byte; version-2 bytes; length-2
+ * bytes And then skipping the 1-byte type encoded by process_heartbeat
+ * for a total of 6 bytes, at which point we can grab the length and the
+ * payload we seek.
+ */
+ fixture.return_payload_offset = 6;
+ return fixture;
+}
static void tear_down(HEARTBEAT_TEST_FIXTURE fixture)
- {
- ERR_print_errors_fp(stderr);
- SSL_free(fixture.s);
- SSL_CTX_free(fixture.ctx);
- }
-
-static void print_payload(const char* const prefix,
- const unsigned char *payload, const int n)
- {
- const int end = n < MAX_PRINTABLE_CHARACTERS ? n
- : MAX_PRINTABLE_CHARACTERS;
- int i = 0;
-
- printf("%s %d character%s", prefix, n, n == 1 ? "" : "s");
- if (end != n) printf(" (first %d shown)", end);
- printf("\n \"");
-
- for (; i != end; ++i)
- {
- const unsigned char c = payload[i];
- if (isprint(c)) fputc(c, stdout);
- else printf("\\x%02x", c);
- }
- printf("\"\n");
- }
+{
+ ERR_print_errors_fp(stderr);
+ SSL_free(fixture.s);
+ SSL_CTX_free(fixture.ctx);
+}
+
+static void print_payload(const char *const prefix,
+ const unsigned char *payload, const int n)
+{
+ const int end = n < MAX_PRINTABLE_CHARACTERS ? n
+ : MAX_PRINTABLE_CHARACTERS;
+ int i = 0;
+
+ printf("%s %d character%s", prefix, n, n == 1 ? "" : "s");
+ if (end != n)
+ printf(" (first %d shown)", end);
+ printf("\n \"");
+
+ for (; i != end; ++i) {
+ const unsigned char c = payload[i];
+ if (isprint(c))
+ fputc(c, stdout);
+ else
+ printf("\\x%02x", c);
+ }
+ printf("\"\n");
+}
static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
- {
- int result = 0;
- SSL* s = fixture.s;
- unsigned char *payload = fixture.payload;
- unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
- int return_value;
- unsigned const char *p;
- int actual_payload_len;
-
- s->s3->rrec.data = payload;
- s->s3->rrec.length = strlen((const char*)payload);
- *payload++ = TLS1_HB_REQUEST;
- s2n(fixture.sent_payload_len, payload);
-
- /* Make a local copy of the request, since it gets overwritten at some
- * point */
- memcpy((char *)sent_buf, (const char*)payload, sizeof(sent_buf));
-
- return_value = fixture.process_heartbeat(s);
-
- if (return_value != fixture.expected_return_value)
- {
- printf("%s failed: expected return value %d, received %d\n",
- fixture.test_case_name, fixture.expected_return_value,
- return_value);
- result = 1;
- }
-
- /* If there is any byte alignment, it will be stored in wbuf.offset. */
- p = &(s->s3->wbuf.buf[
- fixture.return_payload_offset + s->s3->wbuf.offset]);
- actual_payload_len = 0;
- n2s(p, actual_payload_len);
-
- if (actual_payload_len != fixture.expected_payload_len)
- {
- printf("%s failed:\n expected payload len: %d\n received: %d\n",
- fixture.test_case_name, fixture.expected_payload_len,
- actual_payload_len);
- print_payload("sent", sent_buf, strlen((const char*)sent_buf));
- print_payload("received", p, actual_payload_len);
- result = 1;
- }
- else
- {
- char* actual_payload = BUF_strndup((const char*)p, actual_payload_len);
- if (strcmp(actual_payload, fixture.expected_return_payload) != 0)
- {
- printf("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n",
- fixture.test_case_name, fixture.expected_return_payload,
- actual_payload);
- result = 1;
- }
- OPENSSL_free(actual_payload);
- }
-
- if (result != 0)
- {
- printf("** %s failed **\n--------\n", fixture.test_case_name);
- }
- return result;
- }
+{
+ int result = 0;
+ SSL *s = fixture.s;
+ unsigned char *payload = fixture.payload;
+ unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
+ int return_value;
+ unsigned const char *p;
+ int actual_payload_len;
+
+ s->s3->rrec.data = payload;
+ s->s3->rrec.length = strlen((const char *)payload);
+ *payload++ = TLS1_HB_REQUEST;
+ s2n(fixture.sent_payload_len, payload);
+
+ /*
+ * Make a local copy of the request, since it gets overwritten at some
+ * point
+ */
+ memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf));
+
+ return_value = fixture.process_heartbeat(s);
+
+ if (return_value != fixture.expected_return_value) {
+ printf("%s failed: expected return value %d, received %d\n",
+ fixture.test_case_name, fixture.expected_return_value,
+ return_value);
+ result = 1;
+ }
+
+ /*
+ * If there is any byte alignment, it will be stored in wbuf.offset.
+ */
+ p = &(s->s3->
+ wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]);
+ actual_payload_len = 0;
+ n2s(p, actual_payload_len);
+
+ if (actual_payload_len != fixture.expected_payload_len) {
+ printf("%s failed:\n expected payload len: %d\n received: %d\n",
+ fixture.test_case_name, fixture.expected_payload_len,
+ actual_payload_len);
+ print_payload("sent", sent_buf, strlen((const char *)sent_buf));
+ print_payload("received", p, actual_payload_len);
+ result = 1;
+ } else {
+ char *actual_payload =
+ BUF_strndup((const char *)p, actual_payload_len);
+ if (strcmp(actual_payload, fixture.expected_return_payload) != 0) {
+ printf
+ ("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n",
+ fixture.test_case_name, fixture.expected_return_payload,
+ actual_payload);
+ result = 1;
+ }
+ OPENSSL_free(actual_payload);
+ }
+
+ if (result != 0) {
+ printf("** %s failed **\n--------\n", fixture.test_case_name);
+ }
+ return result;
+}
static int honest_payload_size(unsigned char payload_buf[])
- {
- /* Omit three-byte pad at the beginning for type and payload length */
- return strlen((const char*)&payload_buf[3]) - MIN_PADDING_SIZE;
- }
+{
+ /* Omit three-byte pad at the beginning for type and payload length */
+ return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE;
+}
-#define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
+# define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type)
-#define EXECUTE_HEARTBEAT_TEST()\
+# define EXECUTE_HEARTBEAT_TEST()\
EXECUTE_TEST(execute_heartbeat, tear_down)
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"
- " ";
- const int payload_buf_len = honest_payload_size(payload_buf);
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = payload_buf_len;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = payload_buf_len;
- fixture.expected_return_payload = "Not bleeding, sixteen spaces of padding";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ 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"
+ " ";
+ const int payload_buf_len = honest_payload_size(payload_buf);
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = payload_buf_len;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = payload_buf_len;
+ fixture.expected_return_payload =
+ "Not bleeding, sixteen spaces of padding";
+ EXECUTE_HEARTBEAT_TEST();
+}
static int test_dtls1_not_bleeding_empty_payload()
- {
- int payload_buf_len;
-
- SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
- /* 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';
- payload_buf_len = honest_payload_size(payload_buf);
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = payload_buf_len;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = payload_buf_len;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ int payload_buf_len;
+
+ SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
+ /*
+ * 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';
+ payload_buf_len = honest_payload_size(payload_buf);
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = payload_buf_len;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = payload_buf_len;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
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 ";
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = 0;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
+ /* Three-byte pad at the beginning for type and payload length */
+ unsigned char payload_buf[] = " HEARTBLEED ";
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = 0;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
static int test_dtls1_heartbleed_empty_payload()
- {
- SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
- /* 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';
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = 0;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
+ /*
+ * 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';
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = 0;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
static int test_dtls1_heartbleed_excessive_plaintext_length()
- {
- SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
- /* Excluding the NUL at the end, one byte in excess of maximum allowed
- * heartbeat message length */
- unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2];
- memset(payload_buf, ' ', sizeof(payload_buf));
- payload_buf[sizeof(payload_buf) - 1] = '\0';
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = honest_payload_size(payload_buf);
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = 0;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
+ /*
+ * Excluding the NUL at the end, one byte in excess of maximum allowed
+ * heartbeat message length
+ */
+ unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2];
+ memset(payload_buf, ' ', sizeof(payload_buf));
+ payload_buf[sizeof(payload_buf) - 1] = '\0';
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = honest_payload_size(payload_buf);
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = 0;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
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"
- " ";
- const int payload_buf_len = honest_payload_size(payload_buf);
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = payload_buf_len;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = payload_buf_len;
- fixture.expected_return_payload = "Not bleeding, sixteen spaces of padding";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ 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"
+ " ";
+ const int payload_buf_len = honest_payload_size(payload_buf);
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = payload_buf_len;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = payload_buf_len;
+ fixture.expected_return_payload =
+ "Not bleeding, sixteen spaces of padding";
+ EXECUTE_HEARTBEAT_TEST();
+}
static int test_tls1_not_bleeding_empty_payload()
- {
- int payload_buf_len;
-
- SETUP_HEARTBEAT_TEST_FIXTURE(tls);
- /* 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';
- payload_buf_len = honest_payload_size(payload_buf);
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = payload_buf_len;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = payload_buf_len;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ int payload_buf_len;
+
+ SETUP_HEARTBEAT_TEST_FIXTURE(tls);
+ /*
+ * 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';
+ payload_buf_len = honest_payload_size(payload_buf);
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = payload_buf_len;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = payload_buf_len;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
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 ";
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = 0;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
+{
+ SETUP_HEARTBEAT_TEST_FIXTURE(tls);
+ /* Three-byte pad at the beginning for type and payload length */
+ unsigned char payload_buf[] = " HEARTBLEED ";
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = 0;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
static int test_tls1_heartbleed_empty_payload()
- {
- SETUP_HEARTBEAT_TEST_FIXTURE(tls);
- /* 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';
-
- fixture.payload = &payload_buf[0];
- fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
- fixture.expected_return_value = 0;
- fixture.expected_payload_len = 0;
- fixture.expected_return_payload = "";
- EXECUTE_HEARTBEAT_TEST();
- }
-
-#undef EXECUTE_HEARTBEAT_TEST
-#undef SETUP_HEARTBEAT_TEST_FIXTURE
+{
+ SETUP_HEARTBEAT_TEST_FIXTURE(tls);
+ /*
+ * 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';
+
+ fixture.payload = &payload_buf[0];
+ fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
+ fixture.expected_return_value = 0;
+ fixture.expected_payload_len = 0;
+ fixture.expected_return_payload = "";
+ EXECUTE_HEARTBEAT_TEST();
+}
+
+# undef EXECUTE_HEARTBEAT_TEST
+# undef SETUP_HEARTBEAT_TEST_FIXTURE
int main(int argc, char *argv[])
- {
- int num_failed;
-
- SSL_library_init();
- SSL_load_error_strings();
-
- num_failed = test_dtls1_not_bleeding() +
- test_dtls1_not_bleeding_empty_payload() +
- test_dtls1_heartbleed() +
- test_dtls1_heartbleed_empty_payload() +
- /* The following test causes an assertion failure at
- * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g: */
- (OPENSSL_VERSION_NUMBER >= 0x1000107fL ?
- test_dtls1_heartbleed_excessive_plaintext_length() : 0) +
- test_tls1_not_bleeding() +
- test_tls1_not_bleeding_empty_payload() +
- test_tls1_heartbleed() +
- test_tls1_heartbleed_empty_payload() +
- 0;
-
- ERR_print_errors_fp(stderr);
-
- if (num_failed != 0)
- {
- printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : "");
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
-
-#else /* OPENSSL_NO_HEARTBEATS*/
+{
+ int num_failed;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ num_failed = test_dtls1_not_bleeding() +
+ test_dtls1_not_bleeding_empty_payload() +
+ test_dtls1_heartbleed() + test_dtls1_heartbleed_empty_payload() +
+ /*
+ * The following test causes an assertion failure at
+ * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g:
+ */
+ (OPENSSL_VERSION_NUMBER >= 0x1000107fL ?
+ test_dtls1_heartbleed_excessive_plaintext_length() : 0) +
+ test_tls1_not_bleeding() +
+ test_tls1_not_bleeding_empty_payload() +
+ test_tls1_heartbleed() + test_tls1_heartbleed_empty_payload() + 0;
+
+ ERR_print_errors_fp(stderr);
+
+ if (num_failed != 0) {
+ printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : "");
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+#else /* OPENSSL_NO_HEARTBEATS */
int main(int argc, char *argv[])
- {
- return EXIT_SUCCESS;
- }
-#endif /* OPENSSL_NO_HEARTBEATS */
+{
+ return EXIT_SUCCESS;
+}
+#endif /* OPENSSL_NO_HEARTBEATS */
diff --git a/ssl/kssl.c b/ssl/kssl.c
index 950a0c56f1a9..cf585679dccc 100644
--- a/ssl/kssl.c
+++ b/ssl/kssl.c
@@ -1,5 +1,7 @@
/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
-/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+/*
+ * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
+ * 2000.
*/
/* ====================================================================
* Copyright (c) 2000 The OpenSSL Project. All rights reserved.
@@ -9,7 +11,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 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
@@ -55,22 +57,22 @@
*
*/
-
-/* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl
-**
-** 19990701 VRS Started.
-** 200011?? Jeffrey Altman, Richard Levitte
-** Generalized for Heimdal, Newer MIT, & Win32.
-** Integrated into main OpenSSL 0.9.7 snapshots.
-** 20010413 Simon Wilkinson, VRS
-** Real RFC2712 KerberosWrapper replaces AP_REQ.
-*/
+/*-
+ * ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl
+ *
+ * 19990701 VRS Started.
+ * 200011?? Jeffrey Altman, Richard Levitte
+ * Generalized for Heimdal, Newer MIT, & Win32.
+ * Integrated into main OpenSSL 0.9.7 snapshots.
+ * 20010413 Simon Wilkinson, VRS
+ * Real RFC2712 KerberosWrapper replaces AP_REQ.
+ */
#include <openssl/opensslconf.h>
#include <string.h>
-#define KRB5_PRIVATE 1
+#define KRB5_PRIVATE 1
#include <openssl/ssl.h>
#include <openssl/evp.h>
@@ -80,19 +82,19 @@
#ifndef OPENSSL_NO_KRB5
-#ifndef ENOMEM
-#define ENOMEM KRB5KRB_ERR_GENERIC
-#endif
+# ifndef ENOMEM
+# define ENOMEM KRB5KRB_ERR_GENERIC
+# endif
-/*
+/*
* When OpenSSL is built on Windows, we do not want to require that
* the Kerberos DLLs be available in order for the OpenSSL DLLs to
* work. Therefore, all Kerberos routines are loaded at run time
* and we do not link to a .LIB file.
*/
-#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
-/*
+# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+/*
* The purpose of the following pre-processor statements is to provide
* compatibility with different releases of MIT Kerberos for Windows.
* All versions up to 1.2 used macros. But macros do not allow for
@@ -101,2121 +103,2158 @@
* an OpenSSL DLL built on Windows to work whether or not the macro
* or function form of the routines are utilized.
*/
-#ifdef krb5_cc_get_principal
-#define NO_DEF_KRB5_CCACHE
-#undef krb5_cc_get_principal
-#endif
-#define krb5_cc_get_principal kssl_krb5_cc_get_principal
-
-#define krb5_free_data_contents kssl_krb5_free_data_contents
-#define krb5_free_context kssl_krb5_free_context
-#define krb5_auth_con_free kssl_krb5_auth_con_free
-#define krb5_free_principal kssl_krb5_free_principal
-#define krb5_mk_req_extended kssl_krb5_mk_req_extended
-#define krb5_get_credentials kssl_krb5_get_credentials
-#define krb5_cc_default kssl_krb5_cc_default
-#define krb5_sname_to_principal kssl_krb5_sname_to_principal
-#define krb5_init_context kssl_krb5_init_context
-#define krb5_free_ticket kssl_krb5_free_ticket
-#define krb5_rd_req kssl_krb5_rd_req
-#define krb5_kt_default kssl_krb5_kt_default
-#define krb5_kt_resolve kssl_krb5_kt_resolve
+# ifdef krb5_cc_get_principal
+# define NO_DEF_KRB5_CCACHE
+# undef krb5_cc_get_principal
+# endif
+# define krb5_cc_get_principal kssl_krb5_cc_get_principal
+
+# define krb5_free_data_contents kssl_krb5_free_data_contents
+# define krb5_free_context kssl_krb5_free_context
+# define krb5_auth_con_free kssl_krb5_auth_con_free
+# define krb5_free_principal kssl_krb5_free_principal
+# define krb5_mk_req_extended kssl_krb5_mk_req_extended
+# define krb5_get_credentials kssl_krb5_get_credentials
+# define krb5_cc_default kssl_krb5_cc_default
+# define krb5_sname_to_principal kssl_krb5_sname_to_principal
+# define krb5_init_context kssl_krb5_init_context
+# define krb5_free_ticket kssl_krb5_free_ticket
+# define krb5_rd_req kssl_krb5_rd_req
+# define krb5_kt_default kssl_krb5_kt_default
+# define krb5_kt_resolve kssl_krb5_kt_resolve
/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */
-#ifndef krb5_kt_close
-#define krb5_kt_close kssl_krb5_kt_close
-#endif /* krb5_kt_close */
-#ifndef krb5_kt_get_entry
-#define krb5_kt_get_entry kssl_krb5_kt_get_entry
-#endif /* krb5_kt_get_entry */
-#define krb5_auth_con_init kssl_krb5_auth_con_init
-
-#define krb5_principal_compare kssl_krb5_principal_compare
-#define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part
-#define krb5_timeofday kssl_krb5_timeofday
-#define krb5_rc_default kssl_krb5_rc_default
-
-#ifdef krb5_rc_initialize
-#undef krb5_rc_initialize
-#endif
-#define krb5_rc_initialize kssl_krb5_rc_initialize
-
-#ifdef krb5_rc_get_lifespan
-#undef krb5_rc_get_lifespan
-#endif
-#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan
-
-#ifdef krb5_rc_destroy
-#undef krb5_rc_destroy
-#endif
-#define krb5_rc_destroy kssl_krb5_rc_destroy
-
-#define valid_cksumtype kssl_valid_cksumtype
-#define krb5_checksum_size kssl_krb5_checksum_size
-#define krb5_kt_free_entry kssl_krb5_kt_free_entry
-#define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache
-#define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache
-#define krb5_get_server_rcache kssl_krb5_get_server_rcache
+# ifndef krb5_kt_close
+# define krb5_kt_close kssl_krb5_kt_close
+# endif /* krb5_kt_close */
+# ifndef krb5_kt_get_entry
+# define krb5_kt_get_entry kssl_krb5_kt_get_entry
+# endif /* krb5_kt_get_entry */
+# define krb5_auth_con_init kssl_krb5_auth_con_init
+
+# define krb5_principal_compare kssl_krb5_principal_compare
+# define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part
+# define krb5_timeofday kssl_krb5_timeofday
+# define krb5_rc_default kssl_krb5_rc_default
+
+# ifdef krb5_rc_initialize
+# undef krb5_rc_initialize
+# endif
+# define krb5_rc_initialize kssl_krb5_rc_initialize
+
+# ifdef krb5_rc_get_lifespan
+# undef krb5_rc_get_lifespan
+# endif
+# define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan
+
+# ifdef krb5_rc_destroy
+# undef krb5_rc_destroy
+# endif
+# define krb5_rc_destroy kssl_krb5_rc_destroy
+
+# define valid_cksumtype kssl_valid_cksumtype
+# define krb5_checksum_size kssl_krb5_checksum_size
+# define krb5_kt_free_entry kssl_krb5_kt_free_entry
+# define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache
+# define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache
+# define krb5_get_server_rcache kssl_krb5_get_server_rcache
/* Prototypes for built in stubs */
void kssl_krb5_free_data_contents(krb5_context, krb5_data *);
-void kssl_krb5_free_principal(krb5_context, krb5_principal );
+void kssl_krb5_free_principal(krb5_context, krb5_principal);
krb5_error_code kssl_krb5_kt_resolve(krb5_context,
- krb5_const char *,
- krb5_keytab *);
-krb5_error_code kssl_krb5_kt_default(krb5_context,
- krb5_keytab *);
+ krb5_const char *, krb5_keytab *);
+krb5_error_code kssl_krb5_kt_default(krb5_context, krb5_keytab *);
krb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *);
-krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *,
+krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *,
krb5_const krb5_data *,
- krb5_const_principal, krb5_keytab,
- krb5_flags *,krb5_ticket **);
+ krb5_const_principal, krb5_keytab,
+ krb5_flags *, krb5_ticket **);
krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal,
krb5_const_principal);
krb5_error_code kssl_krb5_mk_req_extended(krb5_context,
- krb5_auth_context *,
+ krb5_auth_context *,
krb5_const krb5_flags,
- krb5_data *,
- krb5_creds *,
- krb5_data * );
+ krb5_data *,
+ krb5_creds *, krb5_data *);
krb5_error_code kssl_krb5_init_context(krb5_context *);
void kssl_krb5_free_context(krb5_context);
-krb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache *);
+krb5_error_code kssl_krb5_cc_default(krb5_context, krb5_ccache *);
krb5_error_code kssl_krb5_sname_to_principal(krb5_context,
- krb5_const char *,
- krb5_const char *,
- krb5_int32,
- krb5_principal *);
+ krb5_const char *,
+ krb5_const char *,
+ krb5_int32, krb5_principal *);
krb5_error_code kssl_krb5_get_credentials(krb5_context,
krb5_const krb5_flags,
krb5_ccache,
- krb5_creds *,
- krb5_creds * *);
-krb5_error_code kssl_krb5_auth_con_init(krb5_context,
- krb5_auth_context *);
-krb5_error_code kssl_krb5_cc_get_principal(krb5_context context,
+ krb5_creds *, krb5_creds * *);
+krb5_error_code kssl_krb5_auth_con_init(krb5_context, krb5_auth_context *);
+krb5_error_code kssl_krb5_cc_get_principal(krb5_context context,
krb5_ccache cache,
krb5_principal *principal);
-krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context);
-size_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype);
+krb5_error_code kssl_krb5_auth_con_free(krb5_context, krb5_auth_context);
+size_t kssl_krb5_checksum_size(krb5_context context, krb5_cksumtype ctype);
krb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype);
-krb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * );
-krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context,
- krb5_auth_context,
- krb5_rcache);
-krb5_error_code kssl_krb5_get_server_rcache(krb5_context,
+krb5_error_code krb5_kt_free_entry(krb5_context, krb5_keytab_entry FAR *);
+krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context,
+ krb5_auth_context, krb5_rcache);
+krb5_error_code kssl_krb5_get_server_rcache(krb5_context,
krb5_const krb5_data *,
krb5_rcache *);
-krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context,
+krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context,
krb5_auth_context,
krb5_rcache *);
/* Function pointers (almost all Kerberos functions are _stdcall) */
-static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *)
- =NULL;
-static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal )
- =NULL;
+static void (_stdcall *p_krb5_free_data_contents) (krb5_context, krb5_data *)
+ = NULL;
+static void (_stdcall *p_krb5_free_principal) (krb5_context, krb5_principal)
+ = NULL;
static krb5_error_code(_stdcall *p_krb5_kt_resolve)
- (krb5_context, krb5_const char *, krb5_keytab *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context,
- krb5_keytab *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context,
- krb5_ticket *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context,
- krb5_auth_context *,
+ (krb5_context, krb5_const char *, krb5_keytab *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_kt_default) (krb5_context,
+ krb5_keytab *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_free_ticket) (krb5_context,
+ krb5_ticket *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_rd_req) (krb5_context,
+ krb5_auth_context *,
krb5_const krb5_data *,
- krb5_const_principal,
+ krb5_const_principal,
krb5_keytab, krb5_flags *,
- krb5_ticket **)=NULL;
-static krb5_error_code (_stdcall *p_krb5_mk_req_extended)
- (krb5_context, krb5_auth_context *,
- krb5_const krb5_flags, krb5_data *, krb5_creds *,
- krb5_data * )=NULL;
-static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL;
-static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL;
-static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context,
- krb5_ccache *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_sname_to_principal)
- (krb5_context, krb5_const char *, krb5_const char *,
- krb5_int32, krb5_principal *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_get_credentials)
- (krb5_context, krb5_const krb5_flags, krb5_ccache,
- krb5_creds *, krb5_creds **)=NULL;
-static krb5_error_code (_stdcall *p_krb5_auth_con_init)
- (krb5_context, krb5_auth_context *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_cc_get_principal)
- (krb5_context context, krb5_ccache cache,
- krb5_principal *principal)=NULL;
-static krb5_error_code (_stdcall *p_krb5_auth_con_free)
- (krb5_context, krb5_auth_context)=NULL;
-static krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part)
- (krb5_context, krb5_const krb5_keyblock *,
- krb5_ticket *)=NULL;
-static krb5_error_code (_stdcall *p_krb5_timeofday)
- (krb5_context context, krb5_int32 *timeret)=NULL;
-static krb5_error_code (_stdcall *p_krb5_rc_default)
- (krb5_context context, krb5_rcache *rc)=NULL;
-static krb5_error_code (_stdcall *p_krb5_rc_initialize)
- (krb5_context context, krb5_rcache rc,
- krb5_deltat lifespan)=NULL;
-static krb5_error_code (_stdcall *p_krb5_rc_get_lifespan)
- (krb5_context context, krb5_rcache rc,
- krb5_deltat *lifespan)=NULL;
-static krb5_error_code (_stdcall *p_krb5_rc_destroy)
- (krb5_context context, krb5_rcache rc)=NULL;
-static krb5_boolean (_stdcall *p_krb5_principal_compare)
- (krb5_context, krb5_const_principal, krb5_const_principal)=NULL;
-static size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL;
-static krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL;
-static krb5_error_code (_stdcall *p_krb5_kt_free_entry)
- (krb5_context,krb5_keytab_entry * )=NULL;
-static krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context,
- krb5_auth_context,
- krb5_rcache)=NULL;
-static krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context,
- krb5_const krb5_data *,
- krb5_rcache *)=NULL;
-static krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context,
- krb5_auth_context,
- krb5_rcache *)=NULL;
-static krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context,
- krb5_keytab keytab)=NULL;
-static krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context,
- krb5_keytab keytab,
- krb5_const_principal principal, krb5_kvno vno,
- krb5_enctype enctype, krb5_keytab_entry *entry)=NULL;
+ krb5_ticket **) = NULL;
+static krb5_error_code(_stdcall *p_krb5_mk_req_extended)
+ (krb5_context, krb5_auth_context *,
+ krb5_const krb5_flags, krb5_data *, krb5_creds *, krb5_data *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_init_context) (krb5_context *) = NULL;
+static void (_stdcall *p_krb5_free_context) (krb5_context) = NULL;
+static krb5_error_code(_stdcall *p_krb5_cc_default) (krb5_context,
+ krb5_ccache *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_sname_to_principal)
+ (krb5_context, krb5_const char *, krb5_const char *,
+ krb5_int32, krb5_principal *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_get_credentials)
+ (krb5_context, krb5_const krb5_flags, krb5_ccache,
+ krb5_creds *, krb5_creds **) = NULL;
+static krb5_error_code(_stdcall *p_krb5_auth_con_init)
+ (krb5_context, krb5_auth_context *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_cc_get_principal)
+ (krb5_context context, krb5_ccache cache, krb5_principal *principal) = NULL;
+static krb5_error_code(_stdcall *p_krb5_auth_con_free)
+ (krb5_context, krb5_auth_context) = NULL;
+static krb5_error_code(_stdcall *p_krb5_decrypt_tkt_part)
+ (krb5_context, krb5_const krb5_keyblock *, krb5_ticket *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_timeofday)
+ (krb5_context context, krb5_int32 *timeret) = NULL;
+static krb5_error_code(_stdcall *p_krb5_rc_default)
+ (krb5_context context, krb5_rcache *rc) = NULL;
+static krb5_error_code(_stdcall *p_krb5_rc_initialize)
+ (krb5_context context, krb5_rcache rc, krb5_deltat lifespan) = NULL;
+static krb5_error_code(_stdcall *p_krb5_rc_get_lifespan)
+ (krb5_context context, krb5_rcache rc, krb5_deltat *lifespan) = NULL;
+static krb5_error_code(_stdcall *p_krb5_rc_destroy)
+ (krb5_context context, krb5_rcache rc) = NULL;
+static krb5_boolean(_stdcall *p_krb5_principal_compare)
+ (krb5_context, krb5_const_principal, krb5_const_principal) = NULL;
+static size_t (_stdcall *p_krb5_checksum_size) (krb5_context context,
+ krb5_cksumtype ctype) = NULL;
+static krb5_boolean(_stdcall *p_valid_cksumtype) (krb5_cksumtype ctype) =
+ NULL;
+static krb5_error_code(_stdcall *p_krb5_kt_free_entry)
+ (krb5_context, krb5_keytab_entry *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_auth_con_setrcache) (krb5_context,
+ krb5_auth_context,
+ krb5_rcache) =
+ NULL;
+static krb5_error_code(_stdcall *p_krb5_get_server_rcache) (krb5_context,
+ krb5_const
+ krb5_data *,
+ krb5_rcache *) =
+ NULL;
+static krb5_error_code(*p_krb5_auth_con_getrcache) (krb5_context,
+ krb5_auth_context,
+ krb5_rcache *) = NULL;
+static krb5_error_code(_stdcall *p_krb5_kt_close) (krb5_context context,
+ krb5_keytab keytab) = NULL;
+static krb5_error_code(_stdcall *p_krb5_kt_get_entry) (krb5_context context,
+ krb5_keytab keytab,
+ krb5_const_principal
+ principal,
+ krb5_kvno vno,
+ krb5_enctype enctype,
+ krb5_keytab_entry
+ *entry) = NULL;
static int krb5_loaded = 0; /* only attempt to initialize func ptrs once */
/* Function to Load the Kerberos 5 DLL and initialize function pointers */
-void
-load_krb5_dll(void)
- {
- HANDLE hKRB5_32;
-
- krb5_loaded++;
- hKRB5_32 = LoadLibrary(TEXT("KRB5_32"));
- if (!hKRB5_32)
- return;
-
- (FARPROC) p_krb5_free_data_contents =
- GetProcAddress( hKRB5_32, "krb5_free_data_contents" );
- (FARPROC) p_krb5_free_context =
- GetProcAddress( hKRB5_32, "krb5_free_context" );
- (FARPROC) p_krb5_auth_con_free =
- GetProcAddress( hKRB5_32, "krb5_auth_con_free" );
- (FARPROC) p_krb5_free_principal =
- GetProcAddress( hKRB5_32, "krb5_free_principal" );
- (FARPROC) p_krb5_mk_req_extended =
- GetProcAddress( hKRB5_32, "krb5_mk_req_extended" );
- (FARPROC) p_krb5_get_credentials =
- GetProcAddress( hKRB5_32, "krb5_get_credentials" );
- (FARPROC) p_krb5_cc_get_principal =
- GetProcAddress( hKRB5_32, "krb5_cc_get_principal" );
- (FARPROC) p_krb5_cc_default =
- GetProcAddress( hKRB5_32, "krb5_cc_default" );
- (FARPROC) p_krb5_sname_to_principal =
- GetProcAddress( hKRB5_32, "krb5_sname_to_principal" );
- (FARPROC) p_krb5_init_context =
- GetProcAddress( hKRB5_32, "krb5_init_context" );
- (FARPROC) p_krb5_free_ticket =
- GetProcAddress( hKRB5_32, "krb5_free_ticket" );
- (FARPROC) p_krb5_rd_req =
- GetProcAddress( hKRB5_32, "krb5_rd_req" );
- (FARPROC) p_krb5_principal_compare =
- GetProcAddress( hKRB5_32, "krb5_principal_compare" );
- (FARPROC) p_krb5_decrypt_tkt_part =
- GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" );
- (FARPROC) p_krb5_timeofday =
- GetProcAddress( hKRB5_32, "krb5_timeofday" );
- (FARPROC) p_krb5_rc_default =
- GetProcAddress( hKRB5_32, "krb5_rc_default" );
- (FARPROC) p_krb5_rc_initialize =
- GetProcAddress( hKRB5_32, "krb5_rc_initialize" );
- (FARPROC) p_krb5_rc_get_lifespan =
- GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" );
- (FARPROC) p_krb5_rc_destroy =
- GetProcAddress( hKRB5_32, "krb5_rc_destroy" );
- (FARPROC) p_krb5_kt_default =
- GetProcAddress( hKRB5_32, "krb5_kt_default" );
- (FARPROC) p_krb5_kt_resolve =
- GetProcAddress( hKRB5_32, "krb5_kt_resolve" );
- (FARPROC) p_krb5_auth_con_init =
- GetProcAddress( hKRB5_32, "krb5_auth_con_init" );
- (FARPROC) p_valid_cksumtype =
- GetProcAddress( hKRB5_32, "valid_cksumtype" );
- (FARPROC) p_krb5_checksum_size =
- GetProcAddress( hKRB5_32, "krb5_checksum_size" );
- (FARPROC) p_krb5_kt_free_entry =
- GetProcAddress( hKRB5_32, "krb5_kt_free_entry" );
- (FARPROC) p_krb5_auth_con_setrcache =
- GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" );
- (FARPROC) p_krb5_get_server_rcache =
- GetProcAddress( hKRB5_32, "krb5_get_server_rcache" );
- (FARPROC) p_krb5_auth_con_getrcache =
- GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" );
- (FARPROC) p_krb5_kt_close =
- GetProcAddress( hKRB5_32, "krb5_kt_close" );
- (FARPROC) p_krb5_kt_get_entry =
- GetProcAddress( hKRB5_32, "krb5_kt_get_entry" );
- }
+void load_krb5_dll(void)
+{
+ HANDLE hKRB5_32;
+
+ krb5_loaded++;
+ hKRB5_32 = LoadLibrary(TEXT("KRB5_32"));
+ if (!hKRB5_32)
+ return;
+
+ (FARPROC) p_krb5_free_data_contents =
+ GetProcAddress(hKRB5_32, "krb5_free_data_contents");
+ (FARPROC) p_krb5_free_context =
+ GetProcAddress(hKRB5_32, "krb5_free_context");
+ (FARPROC) p_krb5_auth_con_free =
+ GetProcAddress(hKRB5_32, "krb5_auth_con_free");
+ (FARPROC) p_krb5_free_principal =
+ GetProcAddress(hKRB5_32, "krb5_free_principal");
+ (FARPROC) p_krb5_mk_req_extended =
+ GetProcAddress(hKRB5_32, "krb5_mk_req_extended");
+ (FARPROC) p_krb5_get_credentials =
+ GetProcAddress(hKRB5_32, "krb5_get_credentials");
+ (FARPROC) p_krb5_cc_get_principal =
+ GetProcAddress(hKRB5_32, "krb5_cc_get_principal");
+ (FARPROC) p_krb5_cc_default = GetProcAddress(hKRB5_32, "krb5_cc_default");
+ (FARPROC) p_krb5_sname_to_principal =
+ GetProcAddress(hKRB5_32, "krb5_sname_to_principal");
+ (FARPROC) p_krb5_init_context =
+ GetProcAddress(hKRB5_32, "krb5_init_context");
+ (FARPROC) p_krb5_free_ticket =
+ GetProcAddress(hKRB5_32, "krb5_free_ticket");
+ (FARPROC) p_krb5_rd_req = GetProcAddress(hKRB5_32, "krb5_rd_req");
+ (FARPROC) p_krb5_principal_compare =
+ GetProcAddress(hKRB5_32, "krb5_principal_compare");
+ (FARPROC) p_krb5_decrypt_tkt_part =
+ GetProcAddress(hKRB5_32, "krb5_decrypt_tkt_part");
+ (FARPROC) p_krb5_timeofday = GetProcAddress(hKRB5_32, "krb5_timeofday");
+ (FARPROC) p_krb5_rc_default = GetProcAddress(hKRB5_32, "krb5_rc_default");
+ (FARPROC) p_krb5_rc_initialize =
+ GetProcAddress(hKRB5_32, "krb5_rc_initialize");
+ (FARPROC) p_krb5_rc_get_lifespan =
+ GetProcAddress(hKRB5_32, "krb5_rc_get_lifespan");
+ (FARPROC) p_krb5_rc_destroy = GetProcAddress(hKRB5_32, "krb5_rc_destroy");
+ (FARPROC) p_krb5_kt_default = GetProcAddress(hKRB5_32, "krb5_kt_default");
+ (FARPROC) p_krb5_kt_resolve = GetProcAddress(hKRB5_32, "krb5_kt_resolve");
+ (FARPROC) p_krb5_auth_con_init =
+ GetProcAddress(hKRB5_32, "krb5_auth_con_init");
+ (FARPROC) p_valid_cksumtype = GetProcAddress(hKRB5_32, "valid_cksumtype");
+ (FARPROC) p_krb5_checksum_size =
+ GetProcAddress(hKRB5_32, "krb5_checksum_size");
+ (FARPROC) p_krb5_kt_free_entry =
+ GetProcAddress(hKRB5_32, "krb5_kt_free_entry");
+ (FARPROC) p_krb5_auth_con_setrcache =
+ GetProcAddress(hKRB5_32, "krb5_auth_con_setrcache");
+ (FARPROC) p_krb5_get_server_rcache =
+ GetProcAddress(hKRB5_32, "krb5_get_server_rcache");
+ (FARPROC) p_krb5_auth_con_getrcache =
+ GetProcAddress(hKRB5_32, "krb5_auth_con_getrcache");
+ (FARPROC) p_krb5_kt_close = GetProcAddress(hKRB5_32, "krb5_kt_close");
+ (FARPROC) p_krb5_kt_get_entry =
+ GetProcAddress(hKRB5_32, "krb5_kt_get_entry");
+}
/* Stubs for each function to be dynamicly loaded */
-void
-kssl_krb5_free_data_contents(krb5_context CO, krb5_data * data)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+void kssl_krb5_free_data_contents(krb5_context CO, krb5_data *data)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_free_data_contents )
- p_krb5_free_data_contents(CO,data);
- }
+ if (p_krb5_free_data_contents)
+ p_krb5_free_data_contents(CO, data);
+}
krb5_error_code
-kssl_krb5_mk_req_extended (krb5_context CO,
- krb5_auth_context * pACO,
+kssl_krb5_mk_req_extended(krb5_context CO,
+ krb5_auth_context *pACO,
krb5_const krb5_flags F,
- krb5_data * pD1,
- krb5_creds * pC,
- krb5_data * pD2)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_mk_req_extended )
- return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ krb5_data *pD1, krb5_creds *pC, krb5_data *pD2)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_mk_req_extended)
+ return (p_krb5_mk_req_extended(CO, pACO, F, pD1, pC, pD2));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
krb5_error_code
-kssl_krb5_auth_con_init(krb5_context CO,
- krb5_auth_context * pACO)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_auth_con_init )
- return(p_krb5_auth_con_init(CO,pACO));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+kssl_krb5_auth_con_init(krb5_context CO, krb5_auth_context *pACO)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_auth_con_init)
+ return (p_krb5_auth_con_init(CO, pACO));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
krb5_error_code
-kssl_krb5_auth_con_free (krb5_context CO,
- krb5_auth_context ACO)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_auth_con_free )
- return(p_krb5_auth_con_free(CO,ACO));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+kssl_krb5_auth_con_free(krb5_context CO, krb5_auth_context ACO)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_auth_con_free)
+ return (p_krb5_auth_con_free(CO, ACO));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
krb5_error_code
kssl_krb5_get_credentials(krb5_context CO,
- krb5_const krb5_flags F,
- krb5_ccache CC,
- krb5_creds * pCR,
- krb5_creds ** ppCR)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_get_credentials )
- return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ krb5_const krb5_flags F,
+ krb5_ccache CC, krb5_creds *pCR, krb5_creds **ppCR)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_get_credentials)
+ return (p_krb5_get_credentials(CO, F, CC, pCR, ppCR));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
krb5_error_code
kssl_krb5_sname_to_principal(krb5_context CO,
- krb5_const char * pC1,
- krb5_const char * pC2,
- krb5_int32 I,
- krb5_principal * pPR)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_sname_to_principal )
- return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ krb5_const char *pC1,
+ krb5_const char *pC2,
+ krb5_int32 I, krb5_principal *pPR)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
-krb5_error_code
-kssl_krb5_cc_default(krb5_context CO,
- krb5_ccache * pCC)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_cc_default )
- return(p_krb5_cc_default(CO,pCC));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_sname_to_principal)
+ return (p_krb5_sname_to_principal(CO, pC1, pC2, I, pPR));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-kssl_krb5_init_context(krb5_context * pCO)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_init_context )
- return(p_krb5_init_context(pCO));
- else
- return KRB5KRB_ERR_GENERIC;
- }
-
-void
-kssl_krb5_free_context(krb5_context CO)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_free_context )
- p_krb5_free_context(CO);
- }
-
-void
-kssl_krb5_free_principal(krb5_context c, krb5_principal p)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_free_principal )
- p_krb5_free_principal(c,p);
- }
+krb5_error_code kssl_krb5_cc_default(krb5_context CO, krb5_ccache *pCC)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
-krb5_error_code
-kssl_krb5_kt_resolve(krb5_context con,
- krb5_const char * sz,
- krb5_keytab * kt)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_kt_resolve )
- return(p_krb5_kt_resolve(con,sz,kt));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_cc_default)
+ return (p_krb5_cc_default(CO, pCC));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-kssl_krb5_kt_default(krb5_context con,
- krb5_keytab * kt)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_kt_default )
- return(p_krb5_kt_default(con,kt));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+krb5_error_code kssl_krb5_init_context(krb5_context *pCO)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_init_context)
+ return (p_krb5_init_context(pCO));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
+void kssl_krb5_free_context(krb5_context CO)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_free_context)
+ p_krb5_free_context(CO);
+}
+
+void kssl_krb5_free_principal(krb5_context c, krb5_principal p)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_free_principal)
+ p_krb5_free_principal(c, p);
+}
krb5_error_code
-kssl_krb5_free_ticket(krb5_context con,
- krb5_ticket * kt)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_free_ticket )
- return(p_krb5_free_ticket(con,kt));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+kssl_krb5_kt_resolve(krb5_context con, krb5_const char *sz, krb5_keytab *kt)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_kt_resolve)
+ return (p_krb5_kt_resolve(con, sz, kt));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
+krb5_error_code kssl_krb5_kt_default(krb5_context con, krb5_keytab *kt)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_kt_default)
+ return (p_krb5_kt_default(con, kt));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
+krb5_error_code kssl_krb5_free_ticket(krb5_context con, krb5_ticket *kt)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_free_ticket)
+ return (p_krb5_free_ticket(con, kt));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
-kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon,
- krb5_const krb5_data * data,
- krb5_const_principal princ, krb5_keytab keytab,
- krb5_flags * flags, krb5_ticket ** pptkt)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_rd_req )
- return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+kssl_krb5_rd_req(krb5_context con, krb5_auth_context *pacon,
+ krb5_const krb5_data *data,
+ krb5_const_principal princ, krb5_keytab keytab,
+ krb5_flags *flags, krb5_ticket **pptkt)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_rd_req)
+ return (p_krb5_rd_req(con, pacon, data, princ, keytab, flags, pptkt));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_boolean
krb5_principal_compare(krb5_context con, krb5_const_principal princ1,
- krb5_const_principal princ2)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+ krb5_const_principal princ2)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_principal_compare )
- return(p_krb5_principal_compare(con,princ1,princ2));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_principal_compare)
+ return (p_krb5_principal_compare(con, princ1, princ2));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys,
- krb5_ticket *ticket)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+ krb5_ticket *ticket)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_decrypt_tkt_part )
- return(p_krb5_decrypt_tkt_part(con,keys,ticket));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_decrypt_tkt_part)
+ return (p_krb5_decrypt_tkt_part(con, keys, ticket));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-krb5_timeofday(krb5_context con, krb5_int32 *timeret)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+krb5_error_code krb5_timeofday(krb5_context con, krb5_int32 *timeret)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_timeofday )
- return(p_krb5_timeofday(con,timeret));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_timeofday)
+ return (p_krb5_timeofday(con, timeret));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-krb5_rc_default(krb5_context con, krb5_rcache *rc)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+krb5_error_code krb5_rc_default(krb5_context con, krb5_rcache *rc)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_rc_default )
- return(p_krb5_rc_default(con,rc));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_rc_default)
+ return (p_krb5_rc_default(con, rc));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_rc_initialize )
- return(p_krb5_rc_initialize(con, rc, lifespan));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_rc_initialize)
+ return (p_krb5_rc_initialize(con, rc, lifespan));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_rc_get_lifespan )
- return(p_krb5_rc_get_lifespan(con, rc, lifespanp));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_rc_get_lifespan)
+ return (p_krb5_rc_get_lifespan(con, rc, lifespanp));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-krb5_rc_destroy(krb5_context con, krb5_rcache rc)
- {
- if (!krb5_loaded)
- load_krb5_dll();
-
- if ( p_krb5_rc_destroy )
- return(p_krb5_rc_destroy(con, rc));
- else
- return KRB5KRB_ERR_GENERIC;
- }
-
-size_t
-krb5_checksum_size(krb5_context context,krb5_cksumtype ctype)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+krb5_error_code krb5_rc_destroy(krb5_context con, krb5_rcache rc)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_krb5_checksum_size )
- return(p_krb5_checksum_size(context, ctype));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_rc_destroy)
+ return (p_krb5_rc_destroy(con, rc));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_boolean
-valid_cksumtype(krb5_cksumtype ctype)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+size_t krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
- if ( p_valid_cksumtype )
- return(p_valid_cksumtype(ctype));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ if (p_krb5_checksum_size)
+ return (p_krb5_checksum_size(context, ctype));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
-krb5_error_code
-krb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry)
- {
- if (!krb5_loaded)
- load_krb5_dll();
+krb5_boolean valid_cksumtype(krb5_cksumtype ctype)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_valid_cksumtype)
+ return (p_valid_cksumtype(ctype));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
+krb5_error_code krb5_kt_free_entry(krb5_context con, krb5_keytab_entry *entry)
+{
+ if (!krb5_loaded)
+ load_krb5_dll();
+
+ if (p_krb5_kt_free_entry)
+ return (p_krb5_kt_free_entry(con, entry));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
- if ( p_krb5_kt_free_entry )
- return(p_krb5_kt_free_entry(con,entry));
- else
- return KRB5KRB_ERR_GENERIC;
- }
-
/* Structure definitions */
-#ifndef NO_DEF_KRB5_CCACHE
-#ifndef krb5_x
-#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
-#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
-#endif
-
-typedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */
-
-typedef struct _krb5_ccache
- {
- krb5_magic magic;
- struct _krb5_cc_ops FAR *ops;
- krb5_pointer data;
- } *krb5_ccache;
-
-typedef struct _krb5_cc_ops
- {
- krb5_magic magic;
- char *prefix;
- char * (KRB5_CALLCONV *get_name)
- (krb5_context, krb5_ccache);
- krb5_error_code (KRB5_CALLCONV *resolve)
- (krb5_context, krb5_ccache *, const char *);
- krb5_error_code (KRB5_CALLCONV *gen_new)
- (krb5_context, krb5_ccache *);
- krb5_error_code (KRB5_CALLCONV *init)
- (krb5_context, krb5_ccache, krb5_principal);
- krb5_error_code (KRB5_CALLCONV *destroy)
- (krb5_context, krb5_ccache);
- krb5_error_code (KRB5_CALLCONV *close)
- (krb5_context, krb5_ccache);
- krb5_error_code (KRB5_CALLCONV *store)
- (krb5_context, krb5_ccache, krb5_creds *);
- krb5_error_code (KRB5_CALLCONV *retrieve)
- (krb5_context, krb5_ccache,
- krb5_flags, krb5_creds *, krb5_creds *);
- krb5_error_code (KRB5_CALLCONV *get_princ)
- (krb5_context, krb5_ccache, krb5_principal *);
- krb5_error_code (KRB5_CALLCONV *get_first)
- (krb5_context, krb5_ccache, krb5_cc_cursor *);
- krb5_error_code (KRB5_CALLCONV *get_next)
- (krb5_context, krb5_ccache,
- krb5_cc_cursor *, krb5_creds *);
- krb5_error_code (KRB5_CALLCONV *end_get)
- (krb5_context, krb5_ccache, krb5_cc_cursor *);
- krb5_error_code (KRB5_CALLCONV *remove_cred)
- (krb5_context, krb5_ccache,
- krb5_flags, krb5_creds *);
- krb5_error_code (KRB5_CALLCONV *set_flags)
- (krb5_context, krb5_ccache, krb5_flags);
- } krb5_cc_ops;
-#endif /* NO_DEF_KRB5_CCACHE */
-
-krb5_error_code
-kssl_krb5_cc_get_principal
- (krb5_context context, krb5_ccache cache,
- krb5_principal *principal)
- {
- if ( p_krb5_cc_get_principal )
- return(p_krb5_cc_get_principal(context,cache,principal));
- else
- return(krb5_x
- ((cache)->ops->get_princ,(context, cache, principal)));
- }
+# ifndef NO_DEF_KRB5_CCACHE
+# ifndef krb5_x
+# define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
+# define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
+# endif
+
+typedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */
+
+typedef struct _krb5_ccache {
+ krb5_magic magic;
+ struct _krb5_cc_ops FAR *ops;
+ krb5_pointer data;
+} *krb5_ccache;
+
+typedef struct _krb5_cc_ops {
+ krb5_magic magic;
+ char *prefix;
+ char *(KRB5_CALLCONV *get_name)
+ (krb5_context, krb5_ccache);
+ krb5_error_code(KRB5_CALLCONV *resolve)
+ (krb5_context, krb5_ccache *, const char *);
+ krb5_error_code(KRB5_CALLCONV *gen_new)
+ (krb5_context, krb5_ccache *);
+ krb5_error_code(KRB5_CALLCONV *init)
+ (krb5_context, krb5_ccache, krb5_principal);
+ krb5_error_code(KRB5_CALLCONV *destroy)
+ (krb5_context, krb5_ccache);
+ krb5_error_code(KRB5_CALLCONV *close)
+ (krb5_context, krb5_ccache);
+ krb5_error_code(KRB5_CALLCONV *store)
+ (krb5_context, krb5_ccache, krb5_creds *);
+ krb5_error_code(KRB5_CALLCONV *retrieve)
+ (krb5_context, krb5_ccache, krb5_flags, krb5_creds *, krb5_creds *);
+ krb5_error_code(KRB5_CALLCONV *get_princ)
+ (krb5_context, krb5_ccache, krb5_principal *);
+ krb5_error_code(KRB5_CALLCONV *get_first)
+ (krb5_context, krb5_ccache, krb5_cc_cursor *);
+ krb5_error_code(KRB5_CALLCONV *get_next)
+ (krb5_context, krb5_ccache, krb5_cc_cursor *, krb5_creds *);
+ krb5_error_code(KRB5_CALLCONV *end_get)
+ (krb5_context, krb5_ccache, krb5_cc_cursor *);
+ krb5_error_code(KRB5_CALLCONV *remove_cred)
+ (krb5_context, krb5_ccache, krb5_flags, krb5_creds *);
+ krb5_error_code(KRB5_CALLCONV *set_flags)
+ (krb5_context, krb5_ccache, krb5_flags);
+} krb5_cc_ops;
+# endif /* NO_DEF_KRB5_CCACHE */
+
+krb5_error_code
+ kssl_krb5_cc_get_principal
+ (krb5_context context, krb5_ccache cache, krb5_principal *principal) {
+ if (p_krb5_cc_get_principal)
+ return (p_krb5_cc_get_principal(context, cache, principal));
+ else
+ return (krb5_x((cache)->ops->get_princ, (context, cache, principal)));
+}
krb5_error_code
kssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon,
krb5_rcache rcache)
- {
- if ( p_krb5_auth_con_setrcache )
- return(p_krb5_auth_con_setrcache(con,acon,rcache));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+{
+ if (p_krb5_auth_con_setrcache)
+ return (p_krb5_auth_con_setrcache(con, acon, rcache));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
-kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data,
- krb5_rcache * rcache)
- {
- if ( p_krb5_get_server_rcache )
- return(p_krb5_get_server_rcache(con,data,rcache));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data *data,
+ krb5_rcache *rcache)
+{
+ if (p_krb5_get_server_rcache)
+ return (p_krb5_get_server_rcache(con, data, rcache));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
kssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon,
- krb5_rcache * prcache)
- {
- if ( p_krb5_auth_con_getrcache )
- return(p_krb5_auth_con_getrcache(con,acon, prcache));
- else
- return KRB5KRB_ERR_GENERIC;
- }
-
-krb5_error_code
-kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab)
- {
- if ( p_krb5_kt_close )
- return(p_krb5_kt_close(context,keytab));
- else
- return KRB5KRB_ERR_GENERIC;
- }
+ krb5_rcache *prcache)
+{
+ if (p_krb5_auth_con_getrcache)
+ return (p_krb5_auth_con_getrcache(con, acon, prcache));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
+
+krb5_error_code kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab)
+{
+ if (p_krb5_kt_close)
+ return (p_krb5_kt_close(context, keytab));
+ else
+ return KRB5KRB_ERR_GENERIC;
+}
krb5_error_code
kssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
krb5_const_principal principal, krb5_kvno vno,
krb5_enctype enctype, krb5_keytab_entry *entry)
- {
- if ( p_krb5_kt_get_entry )
- return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry));
- else
- return KRB5KRB_ERR_GENERIC;
- }
-#endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */
-
-
-/* memory allocation functions for non-temporary storage
- * (e.g. stuff that gets saved into the kssl context) */
-static void* kssl_calloc(size_t nmemb, size_t size)
{
- void* p;
-
- p=OPENSSL_malloc(nmemb*size);
- if (p){
- memset(p, 0, nmemb*size);
- }
- return p;
+ if (p_krb5_kt_get_entry)
+ return (p_krb5_kt_get_entry
+ (context, keytab, principal, vno, enctype, entry));
+ else
+ return KRB5KRB_ERR_GENERIC;
}
+# endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */
+
+/*
+ * memory allocation functions for non-temporary storage (e.g. stuff that
+ * gets saved into the kssl context)
+ */
+static void *kssl_calloc(size_t nmemb, size_t size)
+{
+ void *p;
-#define kssl_malloc(size) OPENSSL_malloc((size))
-#define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size)
-#define kssl_free(ptr) OPENSSL_free((ptr))
+ p = OPENSSL_malloc(nmemb * size);
+ if (p) {
+ memset(p, 0, nmemb * size);
+ }
+ return p;
+}
+# define kssl_malloc(size) OPENSSL_malloc((size))
+# define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size)
+# define kssl_free(ptr) OPENSSL_free((ptr))
char
*kstring(char *string)
- {
- static char *null = "[NULL]";
+{
+ static char *null = "[NULL]";
- return ((string == NULL)? null: string);
- }
+ return ((string == NULL) ? null : string);
+}
-/* Given KRB5 enctype (basically DES or 3DES),
-** return closest match openssl EVP_ encryption algorithm.
-** Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes.
-** Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK.
-*/
-const EVP_CIPHER *
-kssl_map_enc(krb5_enctype enctype)
- {
- switch (enctype)
- {
- case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */
- case ENCTYPE_DES_CBC_CRC:
- case ENCTYPE_DES_CBC_MD4:
- case ENCTYPE_DES_CBC_MD5:
- case ENCTYPE_DES_CBC_RAW:
- return EVP_des_cbc();
- break;
- case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */
- case ENCTYPE_DES3_CBC_SHA:
- case ENCTYPE_DES3_CBC_RAW:
- return EVP_des_ede3_cbc();
- break;
- default: return NULL;
- break;
- }
- }
-
-
-/* Return true:1 if p "looks like" the start of the real authenticator
-** described in kssl_skip_confound() below. The ASN.1 pattern is
-** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and
-** xx and yy are possibly multi-byte length fields.
-*/
-static int kssl_test_confound(unsigned char *p)
- {
- int len = 2;
- int xx = 0, yy = 0;
-
- if (*p++ != 0x62) return 0;
- if (*p > 0x82) return 0;
- switch(*p) {
- case 0x82: p++; xx = (*p++ << 8); xx += *p++; break;
- case 0x81: p++; xx = *p++; break;
- case 0x80: return 0;
- default: xx = *p++; break;
- }
- if (*p++ != 0x30) return 0;
- if (*p > 0x82) return 0;
- switch(*p) {
- case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break;
- case 0x81: p++; len++; yy = *p++; break;
- case 0x80: return 0;
- default: yy = *p++; break;
- }
-
- return (xx - len == yy)? 1: 0;
- }
-
-/* Allocate, fill, and return cksumlens array of checksum lengths.
-** This array holds just the unique elements from the krb5_cksumarray[].
-** array[n] == 0 signals end of data.
-**
-** The krb5_cksumarray[] was an internal variable that has since been
-** replaced by a more general method for storing the data. It should
-** not be used. Instead we use real API calls and make a guess for
-** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2
-** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010.
-*/
-static size_t *populate_cksumlens(void)
- {
- int i, j, n;
- static size_t *cklens = NULL;
-
-#ifdef KRB5_MIT_OLD11
- n = krb5_max_cksum;
-#else
- n = 0x0010;
-#endif /* KRB5_MIT_OLD11 */
-
-#ifdef KRB5CHECKAUTH
- if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return NULL;
-
- for (i=0; i < n; i++) {
- if (!valid_cksumtype(i)) continue; /* array has holes */
- for (j=0; j < n; j++) {
- if (cklens[j] == 0) {
- cklens[j] = krb5_checksum_size(NULL,i);
- break; /* krb5 elem was new: add */
- }
- if (cklens[j] == krb5_checksum_size(NULL,i)) {
- break; /* ignore duplicate elements */
- }
- }
- }
-#endif /* KRB5CHECKAUTH */
-
- return cklens;
- }
-
-/* Return pointer to start of real authenticator within authenticator, or
-** return NULL on error.
-** Decrypted authenticator looks like this:
-** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r]
-** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the
-** krb5_auth_con_getcksumtype() function advertised in its krb5.h.
-*/
-unsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a)
- {
- int i, conlen;
- size_t cklen;
- static size_t *cksumlens = NULL;
- unsigned char *test_auth;
-
- conlen = (etype)? 8: 0;
-
- if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL;
- for (i=0; (cklen = cksumlens[i]) != 0; i++)
- {
- test_auth = a + conlen + cklen;
- if (kssl_test_confound(test_auth)) return test_auth;
- }
-
- return NULL;
- }
-
-
-/* Set kssl_err error info when reason text is a simple string
-** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; }
-*/
-void
-kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text)
- {
- if (kssl_err == NULL) return;
+/*
+ * Given KRB5 enctype (basically DES or 3DES), return closest match openssl
+ * EVP_ encryption algorithm. Return NULL for unknown or problematic
+ * (krb5_dk_encrypt) enctypes. Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are
+ * OK.
+ */
+const EVP_CIPHER *kssl_map_enc(krb5_enctype enctype)
+{
+ switch (enctype) {
+ case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_RAW:
+ return EVP_des_cbc();
+ break;
+ case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */
+ case ENCTYPE_DES3_CBC_SHA:
+ case ENCTYPE_DES3_CBC_RAW:
+ return EVP_des_ede3_cbc();
+ break;
+ default:
+ return NULL;
+ break;
+ }
+}
+
+/*
+ * Return true:1 if p "looks like" the start of the real authenticator
+ * described in kssl_skip_confound() below. The ASN.1 pattern is "62 xx 30
+ * yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and xx and yy are
+ * possibly multi-byte length fields.
+ */
+static int kssl_test_confound(unsigned char *p)
+{
+ int len = 2;
+ int xx = 0, yy = 0;
+
+ if (*p++ != 0x62)
+ return 0;
+ if (*p > 0x82)
+ return 0;
+ switch (*p) {
+ case 0x82:
+ p++;
+ xx = (*p++ << 8);
+ xx += *p++;
+ break;
+ case 0x81:
+ p++;
+ xx = *p++;
+ break;
+ case 0x80:
+ return 0;
+ default:
+ xx = *p++;
+ break;
+ }
+ if (*p++ != 0x30)
+ return 0;
+ if (*p > 0x82)
+ return 0;
+ switch (*p) {
+ case 0x82:
+ p++;
+ len += 2;
+ yy = (*p++ << 8);
+ yy += *p++;
+ break;
+ case 0x81:
+ p++;
+ len++;
+ yy = *p++;
+ break;
+ case 0x80:
+ return 0;
+ default:
+ yy = *p++;
+ break;
+ }
+
+ return (xx - len == yy) ? 1 : 0;
+}
- kssl_err->reason = reason;
- BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text);
- return;
+/*
+ * Allocate, fill, and return cksumlens array of checksum lengths. This
+ * array holds just the unique elements from the krb5_cksumarray[]. array[n]
+ * == 0 signals end of data. The krb5_cksumarray[] was an internal variable
+ * that has since been replaced by a more general method for storing the
+ * data. It should not be used. Instead we use real API calls and make a
+ * guess for what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2
+ * it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010.
+ */
+static size_t *populate_cksumlens(void)
+{
+ int i, j, n;
+ static size_t *cklens = NULL;
+
+# ifdef KRB5_MIT_OLD11
+ n = krb5_max_cksum;
+# else
+ n = 0x0010;
+# endif /* KRB5_MIT_OLD11 */
+
+# ifdef KRB5CHECKAUTH
+ if (!cklens && !(cklens = (size_t *)calloc(sizeof(int), n + 1)))
+ return NULL;
+
+ for (i = 0; i < n; i++) {
+ if (!valid_cksumtype(i))
+ continue; /* array has holes */
+ for (j = 0; j < n; j++) {
+ if (cklens[j] == 0) {
+ cklens[j] = krb5_checksum_size(NULL, i);
+ break; /* krb5 elem was new: add */
+ }
+ if (cklens[j] == krb5_checksum_size(NULL, i)) {
+ break; /* ignore duplicate elements */
+ }
}
+ }
+# endif /* KRB5CHECKAUTH */
+
+ return cklens;
+}
+/*-
+ * Return pointer to start of real authenticator within authenticator, or
+ * return NULL on error.