s3_srvr.c revision 9dc0df1bac950d6e491f9a7c7e4888f2b301cb15
/* 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
* 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.]
*/
/* ====================================================================
* 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
* 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
*
* Portions of the attached software ("Contribution") are developed by
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
*
* The Contribution is licensed pursuant to the OpenSSL open source
* license provided above.
*
* ECC cipher suite support in OpenSSL originally written by
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
*
*/
#define REUSE_CIPHER_BUG
#define NETSCAPE_HANG_BUG
#include <stdio.h>
#include "ssl_locl.h"
#include "kssl_lcl.h"
#ifndef OPENSSL_NO_DH
#endif
#ifndef OPENSSL_NO_KRB5
#include <openssl/krb5_asn.h>
#endif
#ifndef OPENSSL_NO_ECDH
static int nid2curve_id(int nid);
#endif
{
if (ver == SSL3_VERSION)
return(SSLv3_server_method());
else
return(NULL);
}
int ssl3_accept(SSL *s)
{
long num1;
int ret= -1;
if (s->info_callback != NULL)
cb=s->info_callback;
/* init things to blank */
s->in_handshake++;
{
return(-1);
}
for (;;)
{
switch (s->state)
{
case SSL_ST_RENEGOTIATE:
s->new_session=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;
{
return -1;
}
s->type=SSL_ST_ACCEPT;
{
{
ret= -1;
goto end;
}
{
ret= -1;
goto end;
}
}
if (!ssl3_setup_buffers(s))
{
ret= -1;
goto end;
}
s->init_num=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 :-)
*/
}
else
{
/* s->state == SSL_ST_RENEGOTIATE,
* we will just send a HelloRequest */
}
break;
case SSL3_ST_SW_HELLO_REQ_A:
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown=0;
s->init_num=0;
break;
case SSL3_ST_SW_HELLO_REQ_C:
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;
s->new_session = 2;
s->init_num=0;
break;
case SSL3_ST_SW_SRVR_HELLO_A:
case SSL3_ST_SW_SRVR_HELLO_B:
if (s->hit)
else
s->init_num=0;
break;
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH */
{
}
else
skip=1;
s->init_num=0;
break;
case SSL3_ST_SW_KEY_EXCH_A:
case SSL3_ST_SW_KEY_EXCH_B:
/* clear this, it may get reset by
* send_server_key_exchange */
if ((s->options & SSL_OP_EPHEMERAL_RSA)
#ifndef OPENSSL_NO_KRB5
&& !(l & SSL_KRB5)
#endif /* OPENSSL_NO_KRB5 */
)
/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
* even when forbidden by protocol specs
* (handshake may fail as clients are not required to
* be able to handle this) */
else
/* only send if a DH key exchange, fortezza or
* RSA but we have a sign only certificate
*
* For ECC ciphersuites, we send a serverKeyExchange
* message only if the cipher suite is either
* ECDH-anon or ECDHE. In other cases, the
* server certificate contains the server's
* public key for key exchange.
*/
|| (l & SSL_kECDHE)
|| ((l & SSL_kRSA)
&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
)
)
)
)
{
}
else
skip=1;
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->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
/* never request cert in anonymous ciphersuites
* (see section "Certificate request" in SSL 3 drafts
* and in RFC 2246): */
/* ... 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 */
{
/* no cert request */
skip=1;
}
else
{
#ifndef NETSCAPE_HANG_BUG
#else
#endif
s->init_num=0;
}
break;
case SSL3_ST_SW_SRVR_DONE_A:
case SSL3_ST_SW_SRVR_DONE_B:
s->init_num=0;
break;
case SSL3_ST_SW_FLUSH:
/* number of bytes to be flushed */
if (num1 > 0)
{
s->rwstate=SSL_WRITING;
s->rwstate=SSL_NOTHING;
}
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)
s->state = SSL3_ST_SR_CLNT_HELLO_C;
else {
{
}
s->init_num=0;
}
break;
case SSL3_ST_SR_KEY_EXCH_A:
case SSL3_ST_SR_KEY_EXCH_B:
if (ret <= 0)
goto end;
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->init_num = 0;
}
else
{
s->init_num=0;
/* We need to get hashes here so if there is
* a client cert, it can be verified
*/
&(s->s3->finish_dgst1),
&(s->s3->finish_dgst2),
}
break;
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
/* we should decide if we expected this one */
s->init_num=0;
break;
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
if (s->hit)
else
s->init_num=0;
break;
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
s->init_num=0;
{
ret= -1;
goto end;
}
break;
case SSL3_ST_SW_FINISHED_A:
case SSL3_ST_SW_FINISHED_B:
if (s->hit)
else
s->init_num=0;
break;
case SSL_ST_OK:
/* clean a few things up */
BUF_MEM_free(s->init_buf);
/* remove buffering on output */
s->init_num=0;
{
/* actually not necessarily a 'new' session unless
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
s->new_session=0;
/* s->server=1; */
}
ret = 1;
goto end;
/* break; */
default:
ret= -1;
goto end;
/* break; */
}
{
if (s->debug)
{
goto end;
}
{
}
}
skip=0;
}
end:
/* BIO_flush(s->wbio); */
s->in_handshake--;
return(ret);
}
int ssl3_send_hello_request(SSL *s)
{
unsigned char *p;
if (s->state == SSL3_ST_SW_HELLO_REQ_A)
{
*(p++)=SSL3_MT_HELLO_REQUEST;
*(p++)=0;
*(p++)=0;
*(p++)=0;
/* number of bytes to write */
s->init_num=4;
s->init_off=0;
}
/* SSL3_ST_SW_HELLO_REQ_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
int ssl3_check_client_hello(SSL *s)
{
int ok;
long n;
/* this function is called when we really expect a Certificate message,
* so permit appropriate message length */
n=s->method->ssl_get_message(s,
-1,
s->max_cert_list,
&ok);
if (!ok) return((int)n);
{
/* Throw away what we have done so far in the current handshake,
* which will now be aborted. (A full SSL_clear would be too much.)
* I hope that tmp.dh is the only thing that may need to be cleared
* when a handshake is not completed ... */
#ifndef OPENSSL_NO_DH
{
}
#endif
return 2;
}
return 1;
}
int ssl3_get_client_hello(SSL *s)
{
unsigned int cookie_len;
long n;
unsigned long id;
unsigned char *p,*d,*q;
SSL_CIPHER *c;
#ifndef OPENSSL_NO_COMP
#endif
/* We do this so that we will respond with our native type.
* If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
* This down switching should be handled by a different method.
* If we are SSLv3, we will respond with SSLv3, even if prompted with
* TLSv1.
*/
if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
{
s->first_packet=1;
}
n=s->method->ssl_get_message(s,
&ok);
if (!ok) return((int)n);
d=p=(unsigned char *)s->init_msg;
/* use version from inside client hello, not from record header
* (may differ: see RFC 2246, Appendix E, second paragraph) */
p+=2;
if (s->client_version < s->version)
{
{
/* similar to ssl3_get_record, send alert using remote version number */
s->version = s->client_version;
}
goto f_err;
}
/* load the client random */
p+=SSL3_RANDOM_SIZE;
/* get the session-id */
j= *(p++);
s->hit=0;
/* Versions before 0.9.7 always allow session reuse during renegotiation
* (i.e. when s->new_session is true), option
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
* Maybe this optional behaviour should always have been the default,
* but we cannot safely change the default behaviour (or new applications
* might be written that become totally unsecure when compiled with
* an earlier library version)
*/
{
if (!ssl_get_new_session(s,1))
goto err;
}
else
{
i=ssl_get_prev_session(s,p,j);
if (i == 1)
{ /* previous session */
s->hit=1;
}
else if (i == -1)
goto err;
else /* i == 0 */
{
if (!ssl_get_new_session(s,1))
goto err;
}
}
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 */
{
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.
*/
{
/* too much data */
goto f_err;
}
/* verify the cookie if appropriate option is set. */
if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
cookie_len > 0)
{
{
cookie_len) == 0)
{
goto f_err;
}
/* else cookie verification succeeded */
}
{
goto f_err;
}
}
p += cookie_len;
}
n2s(p,i);
if ((i == 0) && (j != 0))
{
/* we need a cipher if we are not resuming a session */
goto f_err;
}
if ((p+i) >= (d+n))
{
/* not enough data */
goto f_err;
}
if ((i > 0) && (ssl_bytes_to_cipher_list(s,p,i,&(ciphers))
== NULL))
{
goto err;
}
p+=i;
/* If it is a hit, check that the cipher is in the list */
if ((s->hit) && (i > 0))
{
j=0;
#ifdef CIPHER_DEBUG
#endif
for (i=0; i<sk_SSL_CIPHER_num(ciphers); i++)
{
c=sk_SSL_CIPHER_value(ciphers,i);
#ifdef CIPHER_DEBUG
printf("client [%2d of %2d]:%s\n",
#endif
{
j=1;
break;
}
}
if (j == 0)
{
{
/* Very bad for multi-threading.... */
}
else
{
/* we need to have the cipher in the cipher
* list if we are asked to reuse it */
goto f_err;
}
}
}
/* compression */
i= *(p++);
if ((p+i) > (d+n))
{
/* not enough data */
goto f_err;
}
q=p;
for (j=0; j<i; j++)
{
if (p[j] == 0) break;
}
p+=i;
if (j >= i)
{
/* no compress */
goto f_err;
}
/* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have i-1 compression
* algorithms from the client, starting at q. */
#ifndef OPENSSL_NO_COMP
{ /* See if we have a match */
for (m=0; m<nn; m++)
{
for (o=0; o<i; o++)
{
if (v == q[o])
{
done=1;
break;
}
}
if (done) break;
}
if (done)
else
}
#endif
/* TLS does not mind if there is extra stuff */
#if 0 /* SSL 3.0 does not mind either, so we should disable this test
* (was enabled in 0.9.6d through 0.9.6j and 0.9.7 through 0.9.7b,
if (s->version == SSL3_VERSION)
{
if (p < (d+n))
{
/* wrong number of bytes,
* there could be more to follow */
goto f_err;
}
}
#endif
/* Given s->session->ciphers and SSL_get_ciphers, we must
* pick a cipher */
if (!s->hit)
{
#ifdef OPENSSL_NO_COMP
s->session->compress_meth=0;
#else
#endif
{
goto f_err;
}
SSL_get_ciphers(s));
if (c == NULL)
{
goto f_err;
}
}
else
{
/* Session-id reuse */
#ifdef REUSE_CIPHER_BUG
{
for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
{
c=sk_SSL_CIPHER_value(sk,i);
if (c->algorithms & SSL_eNULL)
nc=c;
if (SSL_C_IS_EXPORT(c))
ec=c;
}
else
}
else
#endif
}
/* we now have the following setup.
* client_random
* cipher_list - our prefered list of ciphers
* ciphers - the clients prefered list of ciphers
* compression - basically ignored right now
* ssl version is set - sslv3
* s->session - The ssl session has been setup.
* s->hit - session reuse flag
* s->tmp.new_cipher - the new cipher to use.
*/
ret=1;
if (0)
{
}
err:
return(ret);
}
int ssl3_send_server_hello(SSL *s)
{
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
unsigned long l,Time;
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
p=s->s3->server_random;
return -1;
/* Do the message type and length last */
d=p= &(buf[4]);
*(p++)=s->version>>8;
*(p++)=s->version&0xff;
/* Random stuff */
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.
*/
s->session->session_id_length=0;
{
return -1;
}
*(p++)=sl;
p+=sl;
/* put the cipher */
p+=i;
/* put the compression method */
#ifdef OPENSSL_NO_COMP
*(p++)=0;
#else
*(p++)=0;
else
#endif
/* do the header */
l=(p-d);
d=buf;
*(d++)=SSL3_MT_SERVER_HELLO;
l2n3(l,d);
/* number of bytes to write */
s->init_off=0;
}
/* SSL3_ST_CW_CLNT_HELLO_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
int ssl3_send_server_done(SSL *s)
{
unsigned char *p;
if (s->state == SSL3_ST_SW_SRVR_DONE_A)
{
/* do the header */
*(p++)=SSL3_MT_SERVER_DONE;
*(p++)=0;
*(p++)=0;
*(p++)=0;
/* number of bytes to write */
s->init_num=4;
s->init_off=0;
}
/* SSL3_ST_CW_CLNT_HELLO_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
int ssl3_send_server_key_exchange(SSL *s)
{
#ifndef OPENSSL_NO_RSA
unsigned char *q;
int j,num;
unsigned int u;
#endif
#ifndef OPENSSL_NO_DH
#endif
#ifndef OPENSSL_NO_ECDH
unsigned char *encodedPoint = NULL;
int encodedlen = 0;
int curve_id = 0;
#endif
unsigned char *p,*d;
int al,i;
unsigned long type;
int n;
BIGNUM *r[4];
if (s->state == SSL3_ST_SW_KEY_EXCH_A)
{
n=0;
#ifndef OPENSSL_NO_RSA
{
{
{
goto f_err;
}
}
{
goto f_err;
}
r[0]=rsa->n;
r[1]=rsa->e;
}
else
#endif
#ifndef OPENSSL_NO_DH
{
{
goto f_err;
}
{
goto err;
}
{
goto err;
}
(s->options & SSL_OP_SINGLE_DH_USE)))
{
if(!DH_generate_key(dh))
{
goto err;
}
}
else
{
{
goto err;
}
}
r[0]=dh->p;
r[1]=dh->g;
}
else
#endif
#ifndef OPENSSL_NO_ECDH
if (type & SSL_kECDHE)
{
{
}
{
goto f_err;
}
{
goto err;
}
/* Duplicate the ECDH structure. */
{
goto err;
}
if (!EC_KEY_up_ref(ecdhp))
{
goto err;
}
(s->options & SSL_OP_SINGLE_ECDH_USE))
{
if(!EC_KEY_generate_key(ecdh))
{
goto err;
}
}
{
goto err;
}
{
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 =
== 0)
{
goto err;
}
/* Encode the public key.
* First check the size of encoding and
* allocate memory accordingly.
*/
encodedPoint = (unsigned char *)
OPENSSL_malloc(encodedlen*sizeof(unsigned char));
bn_ctx = BN_CTX_new();
{
goto err;
}
if (encodedlen == 0)
{
goto err;
}
/* XXX: For now, we only support named (not
* generic) curves in ECDH ephemeral key exchanges.
* In this situation, we need three additional bytes
* to encode the entire ServerECDHParams
* structure.
*/
n = 3 + encodedlen;
/* We'll generate the serverKeyExchange message
* explicitly so we can set these to NULLs
*/
r[0]=NULL;
r[1]=NULL;
r[2]=NULL;
}
else
#endif /* !OPENSSL_NO_ECDH */
{
goto f_err;
}
for (i=0; r[i] != NULL; i++)
{
nr[i]=BN_num_bytes(r[i]);
n+=2+nr[i];
}
{
== NULL)
{
goto f_err;
}
}
else
{
kn=0;
}
{
goto err;
}
p= &(d[4]);
for (i=0; r[i] != NULL; i++)
{
BN_bn2bin(r[i],p);
p+=nr[i];
}
#ifndef OPENSSL_NO_ECDH
if (type & SSL_kECDHE)
{
/* XXX: For now, we only support named (not generic) curves.
* In this situation, the serverKeyExchange message has:
* [1 byte CurveType], [1 byte CurveName]
* [1 byte length of encoded point], followed by
* the actual encoded point itself
*/
*p = NAMED_CURVE_TYPE;
p += 1;
*p = curve_id;
p += 1;
*p = encodedlen;
p += 1;
memcpy((unsigned char*)p,
(unsigned char *)encodedPoint,
p += encodedlen;
}
#endif
/* not anonymous */
{
/* n is the length of the params, they start at &(d[4])
* and p points to the space at the end. */
#ifndef OPENSSL_NO_RSA
{
q=md_buf;
j=0;
{
(unsigned int *)&i);
q+=i;
j+=i;
}
{
goto err;
}
s2n(u,p);
n+=u+2;
}
else
#endif
#if !defined(OPENSSL_NO_DSA)
{
/* lets do DSS */
(unsigned int *)&i,pkey))
{
goto err;
}
s2n(i,p);
n+=i+2;
}
else
#endif
#if !defined(OPENSSL_NO_ECDSA)
{
/* let's do ECDSA */
(unsigned int *)&i,pkey))
{
goto err;
}
s2n(i,p);
n+=i+2;
}
else
#endif
{
/* Is this error check actually needed? */
goto f_err;
}
}
*(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
l2n3(n,d);
/* we should now have things packed up, so lets send
* it off */
s->init_num=n+4;
s->init_off=0;
}
s->state = SSL3_ST_SW_KEY_EXCH_B;
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
err:
#ifndef OPENSSL_NO_ECDH
#endif
return(-1);
}
int ssl3_send_certificate_request(SSL *s)
{
unsigned char *p,*d;
if (s->state == SSL3_ST_SW_CERT_REQ_A)
{
/* 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;
nl=0;
{
for (i=0; i<sk_X509_NAME_num(sk); i++)
{
{
goto err;
}
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);
n+=j;
nl+=j;
}
}
}
/* else no CA names */
*(d++)=SSL3_MT_CERTIFICATE_REQUEST;
l2n3(n,d);
/* we should now have things packed up, so lets send
* it off */
s->init_num=n+4;
s->init_off=0;
#ifdef NETSCAPE_HANG_BUG
/* do the header */
*(p++)=SSL3_MT_SERVER_DONE;
*(p++)=0;
*(p++)=0;
*(p++)=0;
s->init_num += 4;
#endif
s->state = SSL3_ST_SW_CERT_REQ_B;
}
/* SSL3_ST_SW_CERT_REQ_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
err:
return(-1);
}
#ifndef OPENSSL_NO_ECDH
static const int KDF1_SHA1_len = 20;
{
#ifndef OPENSSL_NO_SHA
if (*outlen < SHA_DIGEST_LENGTH)
return NULL;
else
#else
return NULL;
#endif /* OPENSSL_NO_SHA */
}
#endif /* OPENSSL_NO_ECDH */
int ssl3_get_client_key_exchange(SSL *s)
{
long n;
unsigned long l;
unsigned char *p;
#ifndef OPENSSL_NO_RSA
#endif
#ifndef OPENSSL_NO_DH
#endif
#ifndef OPENSSL_NO_KRB5
#endif /* OPENSSL_NO_KRB5 */
#ifndef OPENSSL_NO_ECDH
#endif
n=s->method->ssl_get_message(s,
2048, /* ??? */
&ok);
if (!ok) return((int)n);
p=(unsigned char *)s->init_msg;
#ifndef OPENSSL_NO_RSA
if (l & SSL_kRSA)
{
/* FIX THIS UP EAY EAY EAY EAY */
{
/* Don't do a callback because rsa_tmp should
* be sent already */
{
goto f_err;
}
}
else
{
{
goto f_err;
}
}
/* TLS */
if (s->version > SSL3_VERSION)
{
n2s(p,i);
if (n != i+2)
{
if (!(s->options & SSL_OP_TLS_D5_BUG))
{
goto err;
}
else
p-=2;
}
else
n=i;
}
al = -1;
if (i != SSL_MAX_MASTER_KEY_LENGTH)
{
/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
}
{
/* The premaster secret must contain the same version number as the
* ClientHello to detect version rollback attacks (strangely, the
* protocol does not offer such protection for DH ciphersuites).
* However, buggy clients exist that send the negotiated protocol
* version instead if the server does not support the requested
* protocol version.
* If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
{
/* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
/* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version
* number check as a "bad version oracle" -- an alert would
* reveal that the plaintext corresponding to some ciphertext
* made up by the adversary is properly formatted except
* that the version number is wrong. To avoid such attacks,
* we should treat this just like any other decryption error. */
}
}
if (al != -1)
{
/* Some decryption failure -- use random value instead as countermeasure
* against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
* (see RFC 2246, section 7.4.7.1). */
p[0] = s->client_version >> 8;
if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */
goto err;
}
s->session->master_key_length=
s->session->master_key,
p,i);
OPENSSL_cleanse(p,i);
}
else
#endif
#ifndef OPENSSL_NO_DH
{
n2s(p,i);
if (n != i+2)
{
if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
{
goto err;
}
else
{
p-=2;
i=(int)n;
}
}
if (n == 0L) /* the parameters are in the cert */
{
goto f_err;
}
else
{
{
goto f_err;
}
else
}
{
goto err;
}
if (i <= 0)
{
goto err;
}
s->session->master_key_length=
s->session->master_key,p,i);
OPENSSL_cleanse(p,i);
}
else
#endif
#ifndef OPENSSL_NO_KRB5
if (l & SSL_kKRB5)
{
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH
krb5_timestamp authtime = 0;
n2s(p,i);
enc_ticket.length = i;
{
goto err;
}
enc_ticket.data = (char *)p;
p+=enc_ticket.length;
n2s(p,i);
authenticator.length = i;
{
goto err;
}
authenticator.data = (char *)p;
p+=authenticator.length;
n2s(p,i);
/* Note that the length is checked again below,
** after decryption
*/
{
goto err;
}
{
goto err;
}
&kssl_err)) != 0)
{
#ifdef KSSL_DEBUG
printf("kssl_sget_tkt rtn %d [%d]\n",
#endif /* KSSL_DEBUG */
goto err;
}
/* Note: no authenticator is not considered an error,
** but will return authtime == 0.
*/
{
#ifdef KSSL_DEBUG
printf("kssl_check_authent rtn %d [%d]\n",
#endif /* KSSL_DEBUG */
goto err;
}
{
goto err;
}
#ifdef KSSL_DEBUG
#endif /* KSSL_DEBUG */
goto err;
{
goto err;
}
{
goto err;
}
if (outl > SSL_MAX_MASTER_KEY_LENGTH)
{
goto err;
}
{
goto err;
}
if (outl > SSL_MAX_MASTER_KEY_LENGTH)
{
goto err;
}
s->session->master_key_length=
if (kssl_ctx->client_princ)
{
if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )
{
}
}
/* Was doing kssl_ctx_free() here,
** but it caused problems for apache.
** kssl_ctx = kssl_ctx_free(kssl_ctx);
** if (s->kssl_ctx) s->kssl_ctx = NULL;
*/
}
else
#endif /* OPENSSL_NO_KRB5 */
#ifndef OPENSSL_NO_ECDH
if ((l & SSL_kECDH) || (l & SSL_kECDHE))
{
int ret = 1;
int field_size = 0;
/* initialize structures for server's ECDH key pair */
{
goto err;
}
/* Let's get server private key and group information */
if (l & SSL_kECDH)
{
/* use the certificate */
}
else
{
/* use the ephermeral values we saved when
* generating the ServerKeyExchange msg.
*/
}
{
goto err;
}
/* Let's get client's public key */
{
goto err;
}
if (n == 0L)
{
/* Client Publickey was in Client Certificate */
if (l & SSL_kECDHE)
{
goto f_err;
}
== NULL) ||
{
/* XXX: For now, we do not support client
* authentication using ECDH certificates
* so this branch (n == 0L) of the code is
* never executed. When that support is
* added, we ought to ensure the key
* received in the certificate is
* authorized for key agreement.
* ECDH_compute_key implicitly checks that
* the two ECDH shares are for the same
* group.
*/
goto f_err;
}
}
else
{
/* Get client's public key from encoded point
* in the ClientKeyExchange message.
*/
{
goto err;
}
/* Get encoded point length */
i = *p;
p += 1;
if (EC_POINT_oct2point(group,
clnt_ecpoint, p, i, bn_ctx) == 0)
{
goto err;
}
/* p is pointing to somewhere in the buffer
* currently, so set it to the start
*/
}
/* Compute the shared pre-master secret */
if (field_size <= 0)
{
goto err;
}
/* If field size is not more than 24 octets, then use SHA-1 hash of result;
* otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt;
* this is new with this version of the Internet Draft).
*/
else
if (i <= 0)
{
goto err;
}
/* Compute the master secret */
OPENSSL_cleanse(p, i);
return (ret);
}
else
#endif
{
goto f_err;
}
return(1);
err:
#endif
#ifndef OPENSSL_NO_ECDH
#endif
return(-1);
}
int ssl3_get_cert_verify(SSL *s)
{
unsigned char *p;
long n;
int type=0,i,j;
n=s->method->ssl_get_message(s,
-1,
514, /* 514? */
&ok);
if (!ok) return((int)n);
{
}
else
{
}
{
{
goto f_err;
}
ret=1;
goto end;
}
{
goto f_err;
}
if (!(type & EVP_PKT_SIGN))
{
goto f_err;
}
if (s->s3->change_cipher_spec)
{
goto f_err;
}
/* we now have a signature that we need to verify */
p=(unsigned char *)s->init_msg;
n2s(p,i);
n-=2;
if (i > n)
{
goto f_err;
}
j=EVP_PKEY_size(pkey);
if ((i > j) || (n > j) || (n <= 0))
{
goto f_err;
}
#ifndef OPENSSL_NO_RSA
{
if (i < 0)
{
goto f_err;
}
if (i == 0)
{
goto f_err;
}
}
else
#endif
#ifndef OPENSSL_NO_DSA
{
if (j <= 0)
{
/* bad signature */
goto f_err;
}
}
else
#endif
#ifndef OPENSSL_NO_ECDSA
{
if (j <= 0)
{
/* bad signature */
goto f_err;
}
}
else
#endif
{
goto f_err;
}
ret=1;
if (0)
{
}
end:
return(ret);
}
int ssl3_get_client_certificate(SSL *s)
{
const unsigned char *p,*q;
unsigned char *d;
n=s->method->ssl_get_message(s,
-1,
s->max_cert_list,
&ok);
if (!ok) return((int)n);
{
if ( (s->verify_mode & SSL_VERIFY_PEER) &&
{
goto f_err;
}
/* If tls asked for a client cert, the client must return a 0 list */
{
goto f_err;
}
return(1);
}
{
goto f_err;
}
p=d=(unsigned char *)s->init_msg;
{
goto err;
}
if (llen+3 != n)
{
goto f_err;
}
{
n2l3(p,l);
{
goto f_err;
}
q=p;
if (x == NULL)
{
goto err;
}
if (p != (q+l))
{
goto f_err;
}
if (!sk_X509_push(sk,x))
{
goto err;
}
x=NULL;
nc+=l+3;
}
if (sk_X509_num(sk) <= 0)
{
/* TLS does not mind 0 certs returned */
if (s->version == SSL3_VERSION)
{
goto f_err;
}
/* Fail for TLS only if we required a certificate */
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
{
goto f_err;
}
}
else
{
i=ssl_verify_cert_chain(s,sk);
if (!i)
{
goto f_err;
}
}
/* With the current implementation, sess_cert will always be NULL
* when we arrive here. */
{
{
goto err;
}
}
/* Inconsistency alert: cert_chain does *not* include the
* peer's own certificate, while we do include it in s3_clnt.c */
ret=1;
if (0)
{
}
err:
return(ret);
}
int ssl3_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 */
{
return(0);
}
l=ssl3_output_cert_chain(s,x);
s->init_num=(int)l;
s->init_off=0;
}
/* SSL3_ST_SW_CERT_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
#ifndef OPENSSL_NO_ECDH
/* This is the complement of curve_id2nid in s3_clnt.c. */
static int nid2curve_id(int nid)
{
/* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
* (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
switch (nid) {
case NID_sect163k1: /* sect163k1 (1) */
return 1;
case NID_sect163r1: /* sect163r1 (2) */
return 2;
case NID_sect163r2: /* sect163r2 (3) */
return 3;
case NID_sect193r1: /* sect193r1 (4) */
return 4;
case NID_sect193r2: /* sect193r2 (5) */
return 5;
case NID_sect233k1: /* sect233k1 (6) */
return 6;
case NID_sect233r1: /* sect233r1 (7) */
return 7;
case NID_sect239k1: /* sect239k1 (8) */
return 8;
case NID_sect283k1: /* sect283k1 (9) */
return 9;
case NID_sect283r1: /* sect283r1 (10) */
return 10;
case NID_sect409k1: /* sect409k1 (11) */
return 11;
case NID_sect409r1: /* sect409r1 (12) */
return 12;
case NID_sect571k1: /* sect571k1 (13) */
return 13;
case NID_sect571r1: /* sect571r1 (14) */
return 14;
case NID_secp160k1: /* secp160k1 (15) */
return 15;
case NID_secp160r1: /* secp160r1 (16) */
return 16;
case NID_secp160r2: /* secp160r2 (17) */
return 17;
case NID_secp192k1: /* secp192k1 (18) */
return 18;
case NID_X9_62_prime192v1: /* secp192r1 (19) */
return 19;
case NID_secp224k1: /* secp224k1 (20) */
return 20;
case NID_secp224r1: /* secp224r1 (21) */
return 21;
case NID_secp256k1: /* secp256k1 (22) */
return 22;
case NID_X9_62_prime256v1: /* secp256r1 (23) */
return 23;
case NID_secp384r1: /* secp384r1 (24) */
return 24;
case NID_secp521r1: /* secp521r1 (25) */
return 25;
default:
return 0;
}
}
#endif