Add DTLS support.
This commit is contained in:
@@ -31,6 +31,8 @@ LIBSRC= \
|
||||
s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \
|
||||
s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \
|
||||
t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \
|
||||
d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \
|
||||
d1_both.c d1_enc.c \
|
||||
ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
|
||||
ssl_ciph.c ssl_stat.c ssl_rsa.c \
|
||||
ssl_asn1.c ssl_txt.c ssl_algs.c \
|
||||
@@ -40,6 +42,8 @@ LIBOBJ= \
|
||||
s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
|
||||
s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \
|
||||
t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \
|
||||
d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \
|
||||
d1_both.o d1_enc.o \
|
||||
ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
|
||||
ssl_ciph.o ssl_stat.o ssl_rsa.o \
|
||||
ssl_asn1.o ssl_txt.o ssl_algs.o \
|
||||
@@ -47,7 +51,7 @@ LIBOBJ= \
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h kssl.h
|
||||
EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h
|
||||
HEADER= $(EXHEADER) ssl_locl.h kssl_lcl.h
|
||||
|
||||
ALL= $(GENERAL) $(SRC) $(HEADER)
|
||||
|
||||
1248
ssl/d1_both.c
Normal file
1248
ssl/d1_both.c
Normal file
File diff suppressed because it is too large
Load Diff
1153
ssl/d1_clnt.c
Normal file
1153
ssl/d1_clnt.c
Normal file
File diff suppressed because it is too large
Load Diff
278
ssl/d1_enc.c
Normal file
278
ssl/d1_enc.c
Normal file
@@ -0,0 +1,278 @@
|
||||
/* ssl/d1_enc.c */
|
||||
/*
|
||||
* DTLS implementation written by Nagendra Modadugu
|
||||
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
#include <openssl/comp.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
||||
int dtls1_enc(SSL *s, int send)
|
||||
{
|
||||
SSL3_RECORD *rec;
|
||||
EVP_CIPHER_CTX *ds;
|
||||
unsigned long l;
|
||||
int bs,i,ii,j,k,n=0;
|
||||
const EVP_CIPHER *enc;
|
||||
|
||||
if (send)
|
||||
{
|
||||
if (s->write_hash != NULL)
|
||||
n=EVP_MD_size(s->write_hash);
|
||||
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)
|
||||
RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->read_hash != NULL)
|
||||
n=EVP_MD_size(s->read_hash);
|
||||
ds=s->enc_read_ctx;
|
||||
rec= &(s->s3->rrec);
|
||||
if (s->enc_read_ctx == NULL)
|
||||
enc=NULL;
|
||||
else
|
||||
enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
|
||||
}
|
||||
|
||||
#ifdef KSSL_DEBUG
|
||||
printf("dtls1_enc(%d)\n", send);
|
||||
#endif /* KSSL_DEBUG */
|
||||
|
||||
if ((s->session == NULL) || (ds == NULL) ||
|
||||
(enc == NULL))
|
||||
{
|
||||
memmove(rec->data,rec->input,rec->length);
|
||||
rec->input=rec->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
l=rec->length;
|
||||
bs=EVP_CIPHER_block_size(ds->cipher);
|
||||
|
||||
if ((bs != 1) && send)
|
||||
{
|
||||
i=bs-((int)l%bs);
|
||||
|
||||
/* Add weird padding of upto 256 bytes */
|
||||
|
||||
/* we need to add 'i' padding bytes of value j */
|
||||
j=i-1;
|
||||
if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
|
||||
{
|
||||
if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
|
||||
j++;
|
||||
}
|
||||
for (k=(int)l; k<(int)(l+i); k++)
|
||||
rec->input[k]=j;
|
||||
l+=i;
|
||||
rec->length+=i;
|
||||
}
|
||||
|
||||
#ifdef KSSL_DEBUG
|
||||
{
|
||||
unsigned long ui;
|
||||
printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
|
||||
ds,rec->data,rec->input,l);
|
||||
printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
|
||||
ds->buf_len, ds->cipher->key_len,
|
||||
DES_KEY_SZ, DES_SCHEDULE_SZ,
|
||||
ds->cipher->iv_len);
|
||||
printf("\t\tIV: ");
|
||||
for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
|
||||
printf("\n");
|
||||
printf("\trec->input=");
|
||||
for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif /* KSSL_DEBUG */
|
||||
|
||||
if (!send)
|
||||
{
|
||||
if (l == 0 || l%bs != 0)
|
||||
{
|
||||
SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
|
||||
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_Cipher(ds,rec->data,rec->input,l);
|
||||
|
||||
#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)
|
||||
{
|
||||
ii=i=rec->data[l-1]; /* padding_length */
|
||||
i++;
|
||||
if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
|
||||
{
|
||||
/* First packet is even in size, so check */
|
||||
if ((memcmp(s->s3->read_sequence,
|
||||
"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1))
|
||||
s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
|
||||
if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
|
||||
i--;
|
||||
}
|
||||
/* TLS 1.0 does not bound the number of padding bytes by the block size.
|
||||
* All of them must have value 'padding_length'. */
|
||||
if (i > (int)rec->length)
|
||||
{
|
||||
/* Incorrect padding. SSLerr() and ssl3_alert are done
|
||||
* by caller: we don't want to reveal whether this is
|
||||
* a decryption error or a MAC verification failure
|
||||
* (see http://www.openssl.org/~bodo/tls-cbc.txt)
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
for (j=(int)(l-i); j<(int)l; j++)
|
||||
{
|
||||
if (rec->data[j] != ii)
|
||||
{
|
||||
/* Incorrect padding */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rec->length-=i;
|
||||
|
||||
rec->data += bs; /* skip the implicit IV */
|
||||
rec->input += bs;
|
||||
rec->length -= bs;
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
208
ssl/d1_lib.c
Normal file
208
ssl/d1_lib.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* ssl/d1_lib.c */
|
||||
/*
|
||||
* DTLS implementation written by Nagendra Modadugu
|
||||
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
const char *dtls1_version_str="DTLSv1" OPENSSL_VERSION_PTEXT;
|
||||
|
||||
static long dtls1_default_timeout(void);
|
||||
|
||||
static 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,
|
||||
};
|
||||
|
||||
static SSL_METHOD DTLSv1_data= {
|
||||
DTLS1_VERSION,
|
||||
dtls1_new,
|
||||
dtls1_clear,
|
||||
dtls1_free,
|
||||
ssl_undefined_function,
|
||||
ssl_undefined_function,
|
||||
ssl3_read,
|
||||
ssl3_peek,
|
||||
ssl3_write,
|
||||
ssl3_shutdown,
|
||||
ssl3_renegotiate,
|
||||
ssl3_renegotiate_check,
|
||||
dtls1_get_message,
|
||||
dtls1_read_bytes,
|
||||
dtls1_write_app_data_bytes,
|
||||
dtls1_dispatch_alert,
|
||||
ssl3_ctrl,
|
||||
ssl3_ctx_ctrl,
|
||||
ssl3_get_cipher_by_char,
|
||||
ssl3_put_cipher_by_char,
|
||||
ssl3_pending,
|
||||
ssl3_num_ciphers,
|
||||
ssl3_get_cipher,
|
||||
ssl_bad_method,
|
||||
dtls1_default_timeout,
|
||||
&DTLSv1_enc_data,
|
||||
ssl_undefined_void_function,
|
||||
ssl3_callback_ctrl,
|
||||
ssl3_ctx_callback_ctrl,
|
||||
};
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
SSL_METHOD *dtlsv1_base_method(void)
|
||||
{
|
||||
return(&DTLSv1_data);
|
||||
}
|
||||
|
||||
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->bitmap.length=sizeof(d1->bitmap.map) * 8;
|
||||
d1->unprocessed_rcds.q=pqueue_new();
|
||||
d1->processed_rcds.q=pqueue_new();
|
||||
d1->buffered_messages = pqueue_new();
|
||||
d1->sent_messages=pqueue_new();
|
||||
|
||||
if ( s->server)
|
||||
{
|
||||
d1->cookie_len = sizeof(s->d1->cookie);
|
||||
}
|
||||
|
||||
if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q
|
||||
|| ! d1->buffered_messages || ! d1->sent_messages)
|
||||
{
|
||||
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);
|
||||
OPENSSL_free(d1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
s->d1=d1;
|
||||
s->method->ssl_clear(s);
|
||||
return(1);
|
||||
}
|
||||
|
||||
void dtls1_free(SSL *s)
|
||||
{
|
||||
pitem *item = NULL;
|
||||
hm_fragment *frag = NULL;
|
||||
|
||||
ssl3_free(s);
|
||||
|
||||
while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
|
||||
{
|
||||
OPENSSL_free(item->data);
|
||||
pitem_free(item);
|
||||
}
|
||||
pqueue_free(s->d1->unprocessed_rcds.q);
|
||||
|
||||
while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
|
||||
{
|
||||
OPENSSL_free(item->data);
|
||||
pitem_free(item);
|
||||
}
|
||||
pqueue_free(s->d1->processed_rcds.q);
|
||||
|
||||
while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
|
||||
{
|
||||
frag = (hm_fragment *)item->data;
|
||||
OPENSSL_free(frag->fragment);
|
||||
OPENSSL_free(frag);
|
||||
pitem_free(item);
|
||||
}
|
||||
pqueue_free(s->d1->buffered_messages);
|
||||
|
||||
while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
|
||||
{
|
||||
frag = (hm_fragment *)item->data;
|
||||
OPENSSL_free(frag->fragment);
|
||||
OPENSSL_free(frag);
|
||||
pitem_free(item);
|
||||
}
|
||||
pqueue_free(s->d1->sent_messages);
|
||||
|
||||
OPENSSL_free(s->d1);
|
||||
}
|
||||
|
||||
void dtls1_clear(SSL *s)
|
||||
{
|
||||
ssl3_clear(s);
|
||||
s->version=DTLS1_VERSION;
|
||||
}
|
||||
96
ssl/d1_meth.c
Normal file
96
ssl/d1_meth.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ssl/d1_meth.h */
|
||||
/*
|
||||
* DTLS implementation written by Nagendra Modadugu
|
||||
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
static SSL_METHOD *dtls1_get_method(int ver);
|
||||
static SSL_METHOD *dtls1_get_method(int ver)
|
||||
{
|
||||
if (ver == DTLS1_VERSION)
|
||||
return(DTLSv1_method());
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
SSL_METHOD *DTLSv1_method(void)
|
||||
{
|
||||
static int init=1;
|
||||
static SSL_METHOD DTLSv1_data;
|
||||
|
||||
if (init)
|
||||
{
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD);
|
||||
|
||||
if (init)
|
||||
{
|
||||
memcpy((char *)&DTLSv1_data,(char *)dtlsv1_base_method(),
|
||||
sizeof(SSL_METHOD));
|
||||
DTLSv1_data.ssl_connect=dtls1_connect;
|
||||
DTLSv1_data.ssl_accept=dtls1_accept;
|
||||
DTLSv1_data.get_ssl_method=dtls1_get_method;
|
||||
init=0;
|
||||
}
|
||||
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD);
|
||||
}
|
||||
|
||||
return(&DTLSv1_data);
|
||||
}
|
||||
1707
ssl/d1_pkt.c
Normal file
1707
ssl/d1_pkt.c
Normal file
File diff suppressed because it is too large
Load Diff
1140
ssl/d1_srvr.c
Normal file
1140
ssl/d1_srvr.c
Normal file
File diff suppressed because it is too large
Load Diff
244
ssl/dtls1.h
Normal file
244
ssl/dtls1.h
Normal file
@@ -0,0 +1,244 @@
|
||||
/* ssl/dtls1.h */
|
||||
/*
|
||||
* DTLS implementation written by Nagendra Modadugu
|
||||
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HEADER_DTLS1_H
|
||||
#define HEADER_DTLS1_H
|
||||
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/pqueue.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DTLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 1
|
||||
|
||||
#define DTLS1_VERSION 0x0100
|
||||
#define DTLS1_VERSION_MAJOR 0x01
|
||||
#define DTLS1_VERSION_MINOR 0x00
|
||||
|
||||
#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
|
||||
|
||||
/* lengths of messages */
|
||||
#define DTLS1_COOKIE_LENGTH 32
|
||||
|
||||
#define DTLS1_RT_HEADER_LENGTH 13
|
||||
|
||||
#define DTLS1_HM_HEADER_LENGTH 12
|
||||
|
||||
#define DTLS1_HM_BAD_FRAGMENT -2
|
||||
#define DTLS1_HM_FRAGMENT_RETRY -3
|
||||
|
||||
#define DTLS1_CCS_HEADER_LENGTH 3
|
||||
|
||||
#define DTLS1_AL_HEADER_LENGTH 7
|
||||
|
||||
|
||||
typedef struct dtls1_bitmap_st
|
||||
{
|
||||
unsigned long long map;
|
||||
unsigned long length; /* sizeof the bitmap in bits */
|
||||
unsigned long long max_seq_num; /* max record number seen so far */
|
||||
} DTLS1_BITMAP;
|
||||
|
||||
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 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;
|
||||
} 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;
|
||||
|
||||
/* only matters for handshake messages */
|
||||
unsigned long long next_expected_seq_num;
|
||||
|
||||
/* 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;
|
||||
|
||||
unsigned int mtu; /* max wire packet size */
|
||||
|
||||
struct hm_header_st w_msg_hdr;
|
||||
struct hm_header_st r_msg_hdr;
|
||||
|
||||
struct dtls1_timeout_st timeout;
|
||||
|
||||
/* 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;
|
||||
|
||||
} DTLS1_STATE;
|
||||
|
||||
typedef struct dtls1_record_data_st
|
||||
{
|
||||
unsigned char *packet;
|
||||
unsigned int packet_length;
|
||||
SSL3_BUFFER rbuf;
|
||||
SSL3_RECORD rrec;
|
||||
} DTLS1_RECORD_DATA;
|
||||
|
||||
/* client methods */
|
||||
int dtls1_client_hello(SSL *s);
|
||||
int dtls1_send_client_certificate(SSL *s);
|
||||
int dtls1_send_client_key_exchange(SSL *s);
|
||||
int dtls1_send_client_verify(SSL *s);
|
||||
|
||||
|
||||
/* server methods */
|
||||
int dtls1_send_hello_request(SSL *s);
|
||||
int dtls1_send_server_hello(SSL *s);
|
||||
int dtls1_send_server_certificate(SSL *s);
|
||||
int dtls1_send_server_key_exchange(SSL *s);
|
||||
int dtls1_send_certificate_request(SSL *s);
|
||||
int dtls1_send_server_done(SSL *s);
|
||||
|
||||
/* common methods */
|
||||
int dtls1_send_change_cipher_spec(SSL *s, int a, int b);
|
||||
int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen);
|
||||
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x);
|
||||
int dtls1_read_failed(SSL *s, int code);
|
||||
int dtls1_buffer_message(SSL *s, int ccs);
|
||||
int dtls1_retransmit_message(SSL *s, unsigned short seq,
|
||||
unsigned long frag_off, int *found);
|
||||
void dtls1_clear_record_buffer(SSL *s);
|
||||
void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
|
||||
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
|
||||
void dtls1_reset_seq_numbers(SSL *s, int rw);
|
||||
|
||||
/* 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_ALERT_COUNT 12
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -83,6 +83,10 @@ static SSL_METHOD SSLv23_data= {
|
||||
ssl_undefined_function,
|
||||
ssl_undefined_function,
|
||||
ssl_ok,
|
||||
ssl3_get_message,
|
||||
ssl3_read_bytes,
|
||||
ssl3_write_bytes,
|
||||
ssl3_dispatch_alert,
|
||||
ssl3_ctrl,
|
||||
ssl3_ctx_ctrl,
|
||||
ssl23_get_cipher_by_char,
|
||||
|
||||
@@ -224,6 +224,10 @@ static SSL_METHOD SSLv2_data= {
|
||||
ssl2_shutdown,
|
||||
ssl_ok, /* NULL - renegotiate */
|
||||
ssl_ok, /* NULL - check renegotiate */
|
||||
NULL, /* NULL - ssl_get_message */
|
||||
NULL, /* NULL - ssl_get_record */
|
||||
NULL, /* NULL - ssl_write_bytes */
|
||||
NULL, /* NULL - dispatch_alert */
|
||||
ssl2_ctrl, /* local */
|
||||
ssl2_ctx_ctrl, /* local */
|
||||
ssl2_get_cipher_by_char,
|
||||
|
||||
@@ -197,7 +197,7 @@ int ssl3_get_finished(SSL *s, int a, int b)
|
||||
* change cipher spec message and is in s->s3->tmp.peer_finish_md
|
||||
*/
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
a,
|
||||
b,
|
||||
SSL3_MT_FINISHED,
|
||||
@@ -391,8 +391,8 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
|
||||
{
|
||||
while (s->init_num < 4)
|
||||
{
|
||||
i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],
|
||||
4 - s->init_num, 0);
|
||||
i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
|
||||
&p[s->init_num],4 - s->init_num, 0);
|
||||
if (i <= 0)
|
||||
{
|
||||
s->rwstate=SSL_READING;
|
||||
@@ -472,7 +472,7 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
|
||||
n = s->s3->tmp.message_size - s->init_num;
|
||||
while (n > 0)
|
||||
{
|
||||
i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0);
|
||||
i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0);
|
||||
if (i <= 0)
|
||||
{
|
||||
s->rwstate=SSL_READING;
|
||||
|
||||
@@ -134,17 +134,7 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
static SSL_METHOD *ssl3_get_client_method(int ver);
|
||||
static int ssl3_client_hello(SSL *s);
|
||||
static int ssl3_get_server_hello(SSL *s);
|
||||
static int ssl3_get_certificate_request(SSL *s);
|
||||
static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
|
||||
static int ssl3_get_server_done(SSL *s);
|
||||
static int ssl3_send_client_verify(SSL *s);
|
||||
static int ssl3_send_client_certificate(SSL *s);
|
||||
static int ssl3_send_client_key_exchange(SSL *s);
|
||||
static int ssl3_get_key_exchange(SSL *s);
|
||||
static int ssl3_get_server_certificate(SSL *s);
|
||||
static int ssl3_check_cert_and_algorithm(SSL *s);
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
static int curve_id2nid(int curve_id);
|
||||
@@ -539,7 +529,7 @@ end:
|
||||
}
|
||||
|
||||
|
||||
static int ssl3_client_hello(SSL *s)
|
||||
int ssl3_client_hello(SSL *s)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
@@ -632,7 +622,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_get_server_hello(SSL *s)
|
||||
int ssl3_get_server_hello(SSL *s)
|
||||
{
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
SSL_CIPHER *c;
|
||||
@@ -642,14 +632,41 @@ static int ssl3_get_server_hello(SSL *s)
|
||||
long n;
|
||||
SSL_COMP *comp;
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_CR_SRVR_HELLO_A,
|
||||
SSL3_ST_CR_SRVR_HELLO_B,
|
||||
SSL3_MT_SERVER_HELLO,
|
||||
-1,
|
||||
300, /* ?? */
|
||||
&ok);
|
||||
|
||||
if (!ok) return((int)n);
|
||||
|
||||
if ( SSL_version(s) == DTLS1_VERSION)
|
||||
{
|
||||
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
|
||||
{
|
||||
if ( s->d1->send_cookie == 0)
|
||||
{
|
||||
s->s3->tmp.reuse_message = 1;
|
||||
return 1;
|
||||
}
|
||||
else /* already sent a cookie */
|
||||
{
|
||||
al=SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
|
||||
SSL_R_BAD_MESSAGE_TYPE);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO)
|
||||
{
|
||||
al=SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
d=p=(unsigned char *)s->init_msg;
|
||||
|
||||
if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff)))
|
||||
@@ -777,7 +794,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_get_server_certificate(SSL *s)
|
||||
int ssl3_get_server_certificate(SSL *s)
|
||||
{
|
||||
int al,i,ok,ret= -1;
|
||||
unsigned long n,nc,llen,l;
|
||||
@@ -789,7 +806,7 @@ static int ssl3_get_server_certificate(SSL *s)
|
||||
EVP_PKEY *pkey=NULL;
|
||||
int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_CR_CERT_A,
|
||||
SSL3_ST_CR_CERT_B,
|
||||
-1,
|
||||
@@ -961,7 +978,7 @@ err:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int ssl3_get_key_exchange(SSL *s)
|
||||
int ssl3_get_key_exchange(SSL *s)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2];
|
||||
@@ -987,7 +1004,7 @@ static int ssl3_get_key_exchange(SSL *s)
|
||||
|
||||
/* use same message size as in ssl3_get_certificate_request()
|
||||
* as ServerKeyExchange message may be skipped */
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_CR_KEY_EXCH_A,
|
||||
SSL3_ST_CR_KEY_EXCH_B,
|
||||
-1,
|
||||
@@ -1405,7 +1422,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_get_certificate_request(SSL *s)
|
||||
int ssl3_get_certificate_request(SSL *s)
|
||||
{
|
||||
int ok,ret=0;
|
||||
unsigned long n,nc,l;
|
||||
@@ -1415,7 +1432,7 @@ static int ssl3_get_certificate_request(SSL *s)
|
||||
unsigned char *d;
|
||||
STACK_OF(X509_NAME) *ca_sk=NULL;
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_CR_CERT_REQ_A,
|
||||
SSL3_ST_CR_CERT_REQ_B,
|
||||
-1,
|
||||
@@ -1553,12 +1570,12 @@ static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
|
||||
return(X509_NAME_cmp(*a,*b));
|
||||
}
|
||||
|
||||
static int ssl3_get_server_done(SSL *s)
|
||||
int ssl3_get_server_done(SSL *s)
|
||||
{
|
||||
int ok,ret=0;
|
||||
long n;
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_CR_SRVR_DONE_A,
|
||||
SSL3_ST_CR_SRVR_DONE_B,
|
||||
SSL3_MT_SERVER_DONE,
|
||||
@@ -1592,7 +1609,7 @@ static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ssl3_send_client_key_exchange(SSL *s)
|
||||
int ssl3_send_client_key_exchange(SSL *s)
|
||||
{
|
||||
unsigned char *p,*d;
|
||||
int n;
|
||||
@@ -2087,7 +2104,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_send_client_verify(SSL *s)
|
||||
int ssl3_send_client_verify(SSL *s)
|
||||
{
|
||||
unsigned char *p,*d;
|
||||
unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
|
||||
@@ -2175,7 +2192,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_send_client_certificate(SSL *s)
|
||||
int ssl3_send_client_certificate(SSL *s)
|
||||
{
|
||||
X509 *x509=NULL;
|
||||
EVP_PKEY *pkey=NULL;
|
||||
@@ -2254,7 +2271,7 @@ static int ssl3_send_client_certificate(SSL *s)
|
||||
|
||||
#define has_bits(i,m) (((i)&(m)) == (m))
|
||||
|
||||
static int ssl3_check_cert_and_algorithm(SSL *s)
|
||||
int ssl3_check_cert_and_algorithm(SSL *s)
|
||||
{
|
||||
int i,idx;
|
||||
long algs;
|
||||
|
||||
12
ssl/s3_enc.c
12
ssl/s3_enc.c
@@ -569,7 +569,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
||||
const EVP_MD *hash;
|
||||
unsigned char *p,rec_char;
|
||||
unsigned int md_size;
|
||||
int npad,i;
|
||||
int npad;
|
||||
|
||||
if (send)
|
||||
{
|
||||
@@ -612,13 +612,19 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
||||
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
|
||||
ssl3_record_sequence_update(seq);
|
||||
return(md_size);
|
||||
}
|
||||
|
||||
void ssl3_record_sequence_update(unsigned char *seq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=7; i>=0; i--)
|
||||
{
|
||||
++seq[i];
|
||||
if (seq[i] != 0) break;
|
||||
}
|
||||
|
||||
return(md_size);
|
||||
}
|
||||
|
||||
int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
|
||||
|
||||
16
ssl/s3_lib.c
16
ssl/s3_lib.c
@@ -1381,6 +1381,10 @@ static SSL_METHOD SSLv3_data= {
|
||||
ssl3_shutdown,
|
||||
ssl3_renegotiate,
|
||||
ssl3_renegotiate_check,
|
||||
ssl3_get_message,
|
||||
ssl3_read_bytes,
|
||||
ssl3_write_bytes,
|
||||
ssl3_dispatch_alert,
|
||||
ssl3_ctrl,
|
||||
ssl3_ctx_ctrl,
|
||||
ssl3_get_cipher_by_char,
|
||||
@@ -2141,13 +2145,13 @@ int ssl3_shutdown(SSL *s)
|
||||
{
|
||||
/* resend it if not sent */
|
||||
#if 1
|
||||
ssl3_dispatch_alert(s);
|
||||
s->method->ssl_dispatch_alert(s);
|
||||
#endif
|
||||
}
|
||||
else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN))
|
||||
{
|
||||
/* If we are waiting for a close from our peer, we are closed */
|
||||
ssl3_read_bytes(s,0,NULL,0,0);
|
||||
s->method->ssl_read_bytes(s,0,NULL,0,0);
|
||||
}
|
||||
|
||||
if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) &&
|
||||
@@ -2202,8 +2206,8 @@ int ssl3_write(SSL *s, const void *buf, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA,
|
||||
buf,len);
|
||||
ret=s->method->ssl_write_bytes(s,SSL3_RT_APPLICATION_DATA,
|
||||
buf,len);
|
||||
if (ret <= 0) return(ret);
|
||||
}
|
||||
|
||||
@@ -2217,7 +2221,7 @@ static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
|
||||
clear_sys_error();
|
||||
if (s->s3->renegotiate) ssl3_renegotiate_check(s);
|
||||
s->s3->in_read_app_data=1;
|
||||
ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
|
||||
ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
|
||||
if ((ret == -1) && (s->s3->in_read_app_data == 2))
|
||||
{
|
||||
/* ssl3_read_bytes decided to call s->handshake_func, which
|
||||
@@ -2226,7 +2230,7 @@ static int ssl3_read_internal(SSL *s, void *buf, int len, int peek)
|
||||
* and thinks that application data makes sense here; so disable
|
||||
* handshake processing and try to read application data again. */
|
||||
s->in_handshake++;
|
||||
ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
|
||||
ret=s->method->ssl_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek);
|
||||
s->in_handshake--;
|
||||
}
|
||||
else
|
||||
|
||||
36
ssl/s3_pkt.c
36
ssl/s3_pkt.c
@@ -118,15 +118,9 @@
|
||||
|
||||
static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int len, int create_empty_fragment);
|
||||
static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int len);
|
||||
static int ssl3_get_record(SSL *s);
|
||||
static int do_compress(SSL *ssl);
|
||||
static int do_uncompress(SSL *ssl);
|
||||
static int do_change_cipher_spec(SSL *ssl);
|
||||
|
||||
/* used only by ssl3_get_record */
|
||||
static int ssl3_read_n(SSL *s, int n, int max, int extend)
|
||||
int ssl3_read_n(SSL *s, int n, int max, int extend)
|
||||
{
|
||||
/* If extend == 0, obtain new n-byte packet; if extend == 1, increase
|
||||
* packet by another n bytes.
|
||||
@@ -147,6 +141,14 @@ static int ssl3_read_n(SSL *s, int n, int max, int extend)
|
||||
/* ... now we can act as if 'extend' was set */
|
||||
}
|
||||
|
||||
/* extend reads should not span multiple packets for DTLS */
|
||||
if ( SSL_version(s) == DTLS1_VERSION &&
|
||||
extend)
|
||||
{
|
||||
if ( s->s3->rbuf.left > 0 && n > s->s3->rbuf.left)
|
||||
n = s->s3->rbuf.left;
|
||||
}
|
||||
|
||||
/* if there is enough in the buffer from a previous read, take some */
|
||||
if (s->s3->rbuf.left >= (int)n)
|
||||
{
|
||||
@@ -434,7 +436,7 @@ printf("\n");
|
||||
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG);
|
||||
goto f_err;
|
||||
}
|
||||
if (!do_uncompress(s))
|
||||
if (!ssl3_do_uncompress(s))
|
||||
{
|
||||
al=SSL_AD_DECOMPRESSION_FAILURE;
|
||||
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_DECOMPRESSION);
|
||||
@@ -472,7 +474,7 @@ err:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int do_uncompress(SSL *ssl)
|
||||
int ssl3_do_uncompress(SSL *ssl)
|
||||
{
|
||||
int i;
|
||||
SSL3_RECORD *rr;
|
||||
@@ -489,7 +491,7 @@ static int do_uncompress(SSL *ssl)
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int do_compress(SSL *ssl)
|
||||
int ssl3_do_compress(SSL *ssl)
|
||||
{
|
||||
int i;
|
||||
SSL3_RECORD *wr;
|
||||
@@ -580,7 +582,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
/* If we have an alert to send, lets send it */
|
||||
if (s->s3->alert_dispatch)
|
||||
{
|
||||
i=ssl3_dispatch_alert(s);
|
||||
i=s->method->ssl_dispatch_alert(s);
|
||||
if (i <= 0)
|
||||
return(i);
|
||||
/* if it went, fall through and send more stuff */
|
||||
@@ -655,7 +657,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
||||
/* first we compress */
|
||||
if (s->compress != NULL)
|
||||
{
|
||||
if (!do_compress(s))
|
||||
if (!ssl3_do_compress(s))
|
||||
{
|
||||
SSLerr(SSL_F_DO_SSL3_WRITE,SSL_R_COMPRESSION_FAILURE);
|
||||
goto err;
|
||||
@@ -716,8 +718,8 @@ err:
|
||||
}
|
||||
|
||||
/* if s->s3->wbuf.left != 0, we need to call this */
|
||||
static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int len)
|
||||
int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1091,7 +1093,7 @@ start:
|
||||
s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg);
|
||||
|
||||
s->s3->change_cipher_spec=1;
|
||||
if (!do_change_cipher_spec(s))
|
||||
if (!ssl3_do_change_cipher_spec(s))
|
||||
goto err;
|
||||
else
|
||||
goto start;
|
||||
@@ -1203,7 +1205,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int do_change_cipher_spec(SSL *s)
|
||||
int ssl3_do_change_cipher_spec(SSL *s)
|
||||
{
|
||||
int i;
|
||||
const char *sender;
|
||||
@@ -1260,7 +1262,7 @@ void ssl3_send_alert(SSL *s, int level, int desc)
|
||||
s->s3->send_alert[0]=level;
|
||||
s->s3->send_alert[1]=desc;
|
||||
if (s->s3->wbuf.left == 0) /* data still being written out? */
|
||||
ssl3_dispatch_alert(s);
|
||||
s->method->ssl_dispatch_alert(s);
|
||||
/* else data is still being written out, we will get written
|
||||
* some time in the future */
|
||||
}
|
||||
|
||||
105
ssl/s3_srvr.c
105
ssl/s3_srvr.c
@@ -56,7 +56,7 @@
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -141,16 +141,6 @@
|
||||
#include <openssl/md5.h>
|
||||
|
||||
static SSL_METHOD *ssl3_get_server_method(int ver);
|
||||
static int ssl3_get_client_hello(SSL *s);
|
||||
static int ssl3_check_client_hello(SSL *s);
|
||||
static int ssl3_send_server_hello(SSL *s);
|
||||
static int ssl3_send_server_key_exchange(SSL *s);
|
||||
static int ssl3_send_certificate_request(SSL *s);
|
||||
static int ssl3_send_server_done(SSL *s);
|
||||
static int ssl3_get_client_key_exchange(SSL *s);
|
||||
static int ssl3_get_client_certificate(SSL *s);
|
||||
static int ssl3_get_cert_verify(SSL *s);
|
||||
static int ssl3_send_hello_request(SSL *s);
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
static int nid2curve_id(int nid);
|
||||
@@ -629,7 +619,7 @@ end:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int ssl3_send_hello_request(SSL *s)
|
||||
int ssl3_send_hello_request(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
@@ -651,14 +641,14 @@ static int ssl3_send_hello_request(SSL *s)
|
||||
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
||||
}
|
||||
|
||||
static int ssl3_check_client_hello(SSL *s)
|
||||
int ssl3_check_client_hello(SSL *s)
|
||||
{
|
||||
int ok;
|
||||
long n;
|
||||
|
||||
/* this function is called when we really expect a Certificate message,
|
||||
* so permit appropriate message length */
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_SR_CERT_A,
|
||||
SSL3_ST_SR_CERT_B,
|
||||
-1,
|
||||
@@ -684,9 +674,10 @@ static int ssl3_check_client_hello(SSL *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ssl3_get_client_hello(SSL *s)
|
||||
int ssl3_get_client_hello(SSL *s)
|
||||
{
|
||||
int i,j,ok,al,ret= -1;
|
||||
int cookie_len;
|
||||
long n;
|
||||
unsigned long id;
|
||||
unsigned char *p,*d,*q;
|
||||
@@ -705,7 +696,7 @@ static int ssl3_get_client_hello(SSL *s)
|
||||
s->first_packet=1;
|
||||
s->state=SSL3_ST_SR_CLNT_HELLO_B;
|
||||
}
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_SR_CLNT_HELLO_B,
|
||||
SSL3_ST_SR_CLNT_HELLO_C,
|
||||
SSL3_MT_CLIENT_HELLO,
|
||||
@@ -770,6 +761,68 @@ static int ssl3_get_client_hello(SSL *s)
|
||||
}
|
||||
|
||||
p+=j;
|
||||
|
||||
if (SSL_version(s) == DTLS1_VERSION)
|
||||
{
|
||||
/* cookie stuff */
|
||||
cookie_len = *(p++);
|
||||
|
||||
if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
|
||||
s->d1->send_cookie == 0)
|
||||
{
|
||||
/* HelloVerifyMessage has already been sent */
|
||||
if ( cookie_len != s->d1->cookie_len)
|
||||
{
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The ClientHello may contain a cookie even if the
|
||||
* HelloVerify message has not been sent--make sure that it
|
||||
* does not cause an overflow.
|
||||
*/
|
||||
if ( cookie_len > sizeof(s->d1->rcvd_cookie))
|
||||
{
|
||||
/* too much data */
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
/* verify the cookie if appropriate option is set. */
|
||||
if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
|
||||
cookie_len > 0)
|
||||
{
|
||||
memcpy(s->d1->rcvd_cookie, p, cookie_len);
|
||||
|
||||
if ( s->ctx->app_verify_cookie_cb != NULL)
|
||||
{
|
||||
if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
|
||||
cookie_len) == 0)
|
||||
{
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
/* else cookie verification succeeded */
|
||||
}
|
||||
else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie,
|
||||
s->d1->cookie_len) != 0) /* default verification */
|
||||
{
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
p += cookie_len;
|
||||
}
|
||||
|
||||
n2s(p,i);
|
||||
if ((i == 0) && (j != 0))
|
||||
{
|
||||
@@ -983,7 +1036,7 @@ err:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int ssl3_send_server_hello(SSL *s)
|
||||
int ssl3_send_server_hello(SSL *s)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
@@ -1054,7 +1107,7 @@ static int ssl3_send_server_hello(SSL *s)
|
||||
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
||||
}
|
||||
|
||||
static int ssl3_send_server_done(SSL *s)
|
||||
int ssl3_send_server_done(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
@@ -1078,7 +1131,7 @@ static int ssl3_send_server_done(SSL *s)
|
||||
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
||||
}
|
||||
|
||||
static int ssl3_send_server_key_exchange(SSL *s)
|
||||
int ssl3_send_server_key_exchange(SSL *s)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
unsigned char *q;
|
||||
@@ -1497,7 +1550,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_send_certificate_request(SSL *s)
|
||||
int ssl3_send_certificate_request(SSL *s)
|
||||
{
|
||||
unsigned char *p,*d;
|
||||
int i,j,nl,off,n;
|
||||
@@ -1601,7 +1654,7 @@ static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ssl3_get_client_key_exchange(SSL *s)
|
||||
int ssl3_get_client_key_exchange(SSL *s)
|
||||
{
|
||||
int i,al,ok;
|
||||
long n;
|
||||
@@ -1626,7 +1679,7 @@ static int ssl3_get_client_key_exchange(SSL *s)
|
||||
BN_CTX *bn_ctx = NULL;
|
||||
#endif
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_SR_KEY_EXCH_A,
|
||||
SSL3_ST_SR_KEY_EXCH_B,
|
||||
SSL3_MT_CLIENT_KEY_EXCHANGE,
|
||||
@@ -2138,7 +2191,7 @@ err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int ssl3_get_cert_verify(SSL *s)
|
||||
int ssl3_get_cert_verify(SSL *s)
|
||||
{
|
||||
EVP_PKEY *pkey=NULL;
|
||||
unsigned char *p;
|
||||
@@ -2147,7 +2200,7 @@ static int ssl3_get_cert_verify(SSL *s)
|
||||
int type=0,i,j;
|
||||
X509 *peer;
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_SR_CERT_VRFY_A,
|
||||
SSL3_ST_SR_CERT_VRFY_B,
|
||||
-1,
|
||||
@@ -2293,7 +2346,7 @@ end:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int ssl3_get_client_certificate(SSL *s)
|
||||
int ssl3_get_client_certificate(SSL *s)
|
||||
{
|
||||
int i,ok,al,ret= -1;
|
||||
X509 *x=NULL;
|
||||
@@ -2302,7 +2355,7 @@ static int ssl3_get_client_certificate(SSL *s)
|
||||
unsigned char *d;
|
||||
STACK_OF(X509) *sk=NULL;
|
||||
|
||||
n=ssl3_get_message(s,
|
||||
n=s->method->ssl_get_message(s,
|
||||
SSL3_ST_SR_CERT_A,
|
||||
SSL3_ST_SR_CERT_B,
|
||||
-1,
|
||||
|
||||
41
ssl/ssl.h
41
ssl/ssl.h
@@ -376,6 +376,14 @@ typedef struct ssl_method_st
|
||||
int (*ssl_shutdown)(SSL *s);
|
||||
int (*ssl_renegotiate)(SSL *s);
|
||||
int (*ssl_renegotiate_check)(SSL *s);
|
||||
/* -- begin DTLS -- */
|
||||
long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
|
||||
max, int *ok);
|
||||
int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,
|
||||
int peek);
|
||||
int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
|
||||
int (*ssl_dispatch_alert)(SSL *s);
|
||||
/* -- end DTLS -- */
|
||||
long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
|
||||
long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
|
||||
SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
|
||||
@@ -490,6 +498,11 @@ typedef struct ssl_session_st
|
||||
* This used to be 0x000FFFFFL before 0.9.7. */
|
||||
#define SSL_OP_ALL 0x00000FFFL
|
||||
|
||||
/* DTLS options */
|
||||
#define SSL_OP_NO_QUERY_MTU 0x00001000L
|
||||
/* Turn on Cookie Exchange (on relevant for servers) */
|
||||
#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
|
||||
|
||||
/* As server, disallow session resumption on renegotiation */
|
||||
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
|
||||
/* If set, always create a new key when using tmp_ecdh parameters */
|
||||
@@ -555,6 +568,8 @@ typedef struct ssl_session_st
|
||||
SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
|
||||
#define SSL_get_mode(ssl) \
|
||||
SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
|
||||
#define SSL_set_mtu(ssl, mtu) \
|
||||
SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
|
||||
|
||||
|
||||
void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
|
||||
@@ -679,6 +694,14 @@ struct ssl_ctx_st
|
||||
/* get client cert callback */
|
||||
int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
|
||||
|
||||
/* cookie generate callback */
|
||||
int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie,
|
||||
unsigned int *cookie_len);
|
||||
|
||||
/* verify cookie callback */
|
||||
int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie,
|
||||
unsigned int cookie_len);
|
||||
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
|
||||
const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
|
||||
@@ -775,6 +798,8 @@ struct ssl_ctx_st
|
||||
#define SSL_CTX_get_info_callback(ctx) ((ctx)->info_callback)
|
||||
#define SSL_CTX_set_client_cert_cb(ctx,cb) ((ctx)->client_cert_cb=(cb))
|
||||
#define SSL_CTX_get_client_cert_cb(ctx) ((ctx)->client_cert_cb)
|
||||
#define SSL_CTX_set_cookie_generate_cb(ctx,cb) ((ctx)->app_gen_cookie_cb=(cb))
|
||||
#define SSL_CTX_set_cookie_verify_cb(ctx,cb) ((ctx)->app_verify_cookie_cb=(cb))
|
||||
|
||||
#define SSL_NOTHING 1
|
||||
#define SSL_WRITING 2
|
||||
@@ -790,7 +815,7 @@ struct ssl_ctx_st
|
||||
struct ssl_st
|
||||
{
|
||||
/* protocol version
|
||||
* (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION)
|
||||
* (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
|
||||
*/
|
||||
int version;
|
||||
int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
|
||||
@@ -854,6 +879,7 @@ struct ssl_st
|
||||
|
||||
struct ssl2_state_st *s2; /* SSLv2 variables */
|
||||
struct ssl3_state_st *s3; /* SSLv3 variables */
|
||||
struct dtls1_state_st *d1; /* DTLSv1 variables */
|
||||
|
||||
int read_ahead; /* Read as many input bytes as possible
|
||||
* (for non-blocking reads) */
|
||||
@@ -953,6 +979,7 @@ struct ssl_st
|
||||
#include <openssl/ssl2.h>
|
||||
#include <openssl/ssl3.h>
|
||||
#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
|
||||
#include <openssl/dtls1.h> /* Datagram TLS */
|
||||
#include <openssl/ssl23.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1118,6 +1145,8 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
|
||||
#define SSL_CTRL_SET_MSG_CALLBACK 15
|
||||
#define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
|
||||
|
||||
/* only applies to datagram connections */
|
||||
#define SSL_CTRL_SET_MTU 17
|
||||
/* Stats */
|
||||
#define SSL_CTRL_SESS_NUMBER 20
|
||||
#define SSL_CTRL_SESS_CONNECT 21
|
||||
@@ -1362,6 +1391,10 @@ SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
|
||||
SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */
|
||||
SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */
|
||||
|
||||
SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
|
||||
SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */
|
||||
SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */
|
||||
|
||||
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
|
||||
|
||||
int SSL_do_handshake(SSL *s);
|
||||
@@ -1657,6 +1690,9 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
|
||||
#define SSL_F_WRITE_PENDING 212
|
||||
|
||||
#define SSL_F_DTLS1_READ_FAILED 1001
|
||||
#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 1002
|
||||
|
||||
/* Reason codes. */
|
||||
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
|
||||
#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
|
||||
@@ -1895,6 +1931,9 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_R_X509_LIB 268
|
||||
#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
|
||||
|
||||
#define SSL_R_READ_TIMEOUT_EXPIRED 2001
|
||||
#define SSL_R_COOKIE_MISMATCH 2002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
37
ssl/ssl3.h
37
ssl/ssl3.h
@@ -294,6 +294,8 @@ typedef struct ssl3_record_st
|
||||
/*rw*/ unsigned char *data; /* pointer to the record data */
|
||||
/*rw*/ unsigned char *input; /* where the decode bytes are */
|
||||
/*r */ unsigned char *comp; /* only used with decompression - malloc()ed */
|
||||
/*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */
|
||||
/*r */ unsigned long long seq_num; /* sequence number, needed by DTLS1 */
|
||||
} SSL3_RECORD;
|
||||
|
||||
typedef struct ssl3_buffer_st
|
||||
@@ -435,6 +437,35 @@ typedef struct ssl3_state_st
|
||||
|
||||
} SSL3_STATE;
|
||||
|
||||
|
||||
/* client methods */
|
||||
int ssl3_client_hello(SSL *s);
|
||||
int ssl3_get_server_hello(SSL *s);
|
||||
int ssl3_get_certificate_request(SSL *s);
|
||||
int ssl3_get_server_done(SSL *s);
|
||||
int ssl3_send_client_verify(SSL *s);
|
||||
int ssl3_send_client_certificate(SSL *s);
|
||||
int ssl3_send_client_key_exchange(SSL *s);
|
||||
int ssl3_get_key_exchange(SSL *s);
|
||||
int ssl3_get_server_certificate(SSL *s);
|
||||
int ssl3_check_cert_and_algorithm(SSL *s);
|
||||
|
||||
/* server methods */
|
||||
int ssl3_get_client_hello(SSL *s);
|
||||
int ssl3_send_server_hello(SSL *s);
|
||||
int ssl3_send_hello_request(SSL *s);
|
||||
int ssl3_send_server_key_exchange(SSL *s);
|
||||
int ssl3_send_certificate_request(SSL *s);
|
||||
int ssl3_send_server_done(SSL *s);
|
||||
int ssl3_check_client_hello(SSL *s);
|
||||
int ssl3_get_client_certificate(SSL *s);
|
||||
int ssl3_get_client_key_exchange(SSL *s);
|
||||
int ssl3_get_cert_verify(SSL *s);
|
||||
|
||||
/* utility functions */
|
||||
void ssl3_record_sequence_update(unsigned char *seq);
|
||||
int ssl3_do_change_cipher_spec(SSL *ssl);
|
||||
|
||||
/* SSLv3 */
|
||||
/*client */
|
||||
/* extra state */
|
||||
@@ -445,6 +476,8 @@ typedef struct ssl3_state_st
|
||||
/* read from server */
|
||||
#define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT)
|
||||
#define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT)
|
||||
#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT)
|
||||
#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT)
|
||||
#define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT)
|
||||
#define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT)
|
||||
#define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT)
|
||||
@@ -481,6 +514,8 @@ typedef struct ssl3_state_st
|
||||
#define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT)
|
||||
#define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT)
|
||||
/* write to client */
|
||||
#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
|
||||
#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
|
||||
#define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT)
|
||||
#define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT)
|
||||
#define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT)
|
||||
@@ -521,6 +556,8 @@ typedef struct ssl3_state_st
|
||||
#define SSL3_MT_CERTIFICATE_VERIFY 15
|
||||
#define SSL3_MT_CLIENT_KEY_EXCHANGE 16
|
||||
#define SSL3_MT_FINISHED 20
|
||||
#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
|
||||
|
||||
|
||||
#define SSL3_MT_CCS 1
|
||||
|
||||
|
||||
@@ -456,6 +456,8 @@ static ERR_STRING_DATA SSL_str_reasons[]=
|
||||
{ERR_REASON(SSL_R_WRONG_VERSION_NUMBER) ,"wrong version number"},
|
||||
{ERR_REASON(SSL_R_X509_LIB) ,"x509 lib"},
|
||||
{ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS),"x509 verification setup problems"},
|
||||
{ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED) ,"read timeout expired"},
|
||||
{ERR_REASON(SSL_R_COOKIE_MISMATCH) ,"cookie mismatch"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -957,6 +957,13 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
|
||||
l=s->max_cert_list;
|
||||
s->max_cert_list=larg;
|
||||
return(l);
|
||||
case SSL_CTRL_SET_MTU:
|
||||
if (SSL_version(s) == DTLS1_VERSION)
|
||||
{
|
||||
s->d1->mtu = larg;
|
||||
return larg;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return(s->method->ssl_ctrl(s,cmd,larg,parg));
|
||||
}
|
||||
@@ -1368,6 +1375,8 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
|
||||
ret->default_passwd_callback=0;
|
||||
ret->default_passwd_callback_userdata=NULL;
|
||||
ret->client_cert_cb=0;
|
||||
ret->app_gen_cookie_cb=0;
|
||||
ret->app_verify_cookie_cb=0;
|
||||
|
||||
ret->sessions=lh_new(LHASH_HASH_FN(SSL_SESSION_hash),
|
||||
LHASH_COMP_FN(SSL_SESSION_cmp));
|
||||
|
||||
@@ -176,6 +176,20 @@
|
||||
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l) )&0xff))
|
||||
|
||||
#define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>>32)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l) )&0xff))
|
||||
|
||||
#define n2l6(c,l) (l =((unsigned long long)(*((c)++)))<<40, \
|
||||
l|=((unsigned long long)(*((c)++)))<<32, \
|
||||
l|=((unsigned long long)(*((c)++)))<<24, \
|
||||
l|=((unsigned long long)(*((c)++)))<<16, \
|
||||
l|=((unsigned long long)(*((c)++)))<< 8, \
|
||||
l|=((unsigned long long)(*((c)++))))
|
||||
|
||||
/* NOTE - c is not incremented as per l2c */
|
||||
#define l2cn(l1,l2,c,n) { \
|
||||
c+=n; \
|
||||
@@ -608,6 +622,21 @@ long ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
|
||||
long ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void));
|
||||
int ssl3_pending(const SSL *s);
|
||||
|
||||
/* -- begin DTLS -- */
|
||||
int dtls1_do_write(SSL *s,int type);
|
||||
int ssl3_read_n(SSL *s, int n, int max, int extend);
|
||||
int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
|
||||
int ssl3_do_compress(SSL *ssl);
|
||||
int ssl3_do_uncompress(SSL *ssl);
|
||||
int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int 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);
|
||||
int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len);
|
||||
int dtls1_write_bytes(SSL *s, int type, const void *buf, int len);
|
||||
/* -- end DTLS -- */
|
||||
|
||||
int ssl23_accept(SSL *s);
|
||||
int ssl23_connect(SSL *s);
|
||||
int ssl23_read_bytes(SSL *s, int n);
|
||||
@@ -620,6 +649,23 @@ long tls1_ctrl(SSL *s,int cmd, long larg, void *parg);
|
||||
long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)(void));
|
||||
SSL_METHOD *tlsv1_base_method(void );
|
||||
|
||||
/* -- start DTLS functions -- */
|
||||
int dtls1_new(SSL *s);
|
||||
int dtls1_accept(SSL *s);
|
||||
int dtls1_connect(SSL *s);
|
||||
void dtls1_free(SSL *s);
|
||||
void dtls1_clear(SSL *s);
|
||||
long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
|
||||
SSL_METHOD *dtlsv1_base_method(void );
|
||||
|
||||
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
|
||||
int dtls1_get_record(SSL *s);
|
||||
int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
|
||||
unsigned int len, int create_empty_fragement);
|
||||
int dtls1_dispatch_alert(SSL *s);
|
||||
int dtls1_enc(SSL *s, int snd);
|
||||
/* -- end DTLS functions -- */
|
||||
|
||||
int ssl_init_wbio_buffer(SSL *s, int push);
|
||||
void ssl_free_wbio_buffer(SSL *s);
|
||||
|
||||
|
||||
@@ -204,6 +204,11 @@ int ssl_get_new_session(SSL *s, int session)
|
||||
ss->ssl_version=TLS1_VERSION;
|
||||
ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
|
||||
}
|
||||
else if (s->version == DTLS1_VERSION)
|
||||
{
|
||||
ss->ssl_version=DTLS1_VERSION;
|
||||
ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
|
||||
|
||||
21
ssl/t1_enc.c
21
ssl/t1_enc.c
@@ -284,7 +284,9 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
if (s->s3->rrec.comp == NULL)
|
||||
goto err;
|
||||
}
|
||||
memset(&(s->s3->read_sequence[0]),0,8);
|
||||
/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
|
||||
if (s->version != DTLS1_VERSION)
|
||||
memset(&(s->s3->read_sequence[0]),0,8);
|
||||
mac_secret= &(s->s3->read_mac_secret[0]);
|
||||
}
|
||||
else
|
||||
@@ -313,7 +315,9 @@ int tls1_change_cipher_state(SSL *s, int which)
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
memset(&(s->s3->write_sequence[0]),0,8);
|
||||
/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
|
||||
if (s->version != DTLS1_VERSION)
|
||||
memset(&(s->s3->write_sequence[0]),0,8);
|
||||
mac_secret= &(s->s3->write_mac_secret[0]);
|
||||
}
|
||||
|
||||
@@ -742,10 +746,13 @@ printf("rec=");
|
||||
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
|
||||
#endif
|
||||
|
||||
for (i=7; i>=0; i--)
|
||||
{
|
||||
++seq[i];
|
||||
if (seq[i] != 0) break;
|
||||
if ( SSL_version(ssl) != DTLS1_VERSION)
|
||||
{
|
||||
for (i=7; i>=0; i--)
|
||||
{
|
||||
++seq[i];
|
||||
if (seq[i] != 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TLS_DEBUG
|
||||
@@ -808,6 +815,8 @@ int tls1_alert_code(int code)
|
||||
case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR);
|
||||
case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED);
|
||||
case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION);
|
||||
case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return
|
||||
(DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
|
||||
default: return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,10 @@ static SSL_METHOD TLSv1_data= {
|
||||
ssl3_shutdown,
|
||||
ssl3_renegotiate,
|
||||
ssl3_renegotiate_check,
|
||||
ssl3_get_message,
|
||||
ssl3_read_bytes,
|
||||
ssl3_write_bytes,
|
||||
ssl3_dispatch_alert,
|
||||
ssl3_ctrl,
|
||||
ssl3_ctx_ctrl,
|
||||
ssl3_get_cipher_by_char,
|
||||
|
||||
Reference in New Issue
Block a user