* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2006 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
* The Contribution is licensed pursuant to the OpenSSL open source
* license provided above.
*
- * In addition, Sun covenants to all licensees who provide a reciprocal
- * covenant with respect to their own patents if any, not to sue under
- * current and future patent claims necessarily infringed by the making,
- * using, practicing, selling, offering for sale and/or otherwise
- * disposing of the Contribution as delivered hereunder
- * (or portions thereof), provided that such covenant shall not apply:
- * 1) for code that a licensee deletes from the Contribution;
- * 2) separates from the Contribution; or
- * 3) for infringements caused by:
- * i) the modification of the Contribution or
- * ii) the combination of the Contribution with other software or
- * devices where such combination causes the infringement.
- *
* ECC cipher suite support in OpenSSL originally written by
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
*
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_KRB5
#include <openssl/krb5_asn.h>
+#endif
#include <openssl/md5.h>
-#include "cryptlib.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);
+
+static const SSL_METHOD *ssl3_get_server_method(int ver);
#ifndef OPENSSL_NO_ECDH
static int nid2curve_id(int nid);
#endif
-static SSL_METHOD *ssl3_get_server_method(int ver)
+static const SSL_METHOD *ssl3_get_server_method(int ver)
{
if (ver == SSL3_VERSION)
return(SSLv3_server_method());
return(NULL);
}
-SSL_METHOD *SSLv3_server_method(void)
- {
- static int init=1;
- static SSL_METHOD SSLv3_server_data;
-
- if (init)
- {
- CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD);
-
- if (init)
- {
- memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(),
- sizeof(SSL_METHOD));
- SSLv3_server_data.ssl_accept=ssl3_accept;
- SSLv3_server_data.get_ssl_method=ssl3_get_server_method;
- init=0;
- }
-
- CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD);
- }
- return(&SSLv3_server_data);
- }
+IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
+ ssl3_accept,
+ ssl_undefined_function,
+ ssl3_get_server_method)
int ssl3_accept(SSL *s)
{
BUF_MEM *buf;
- unsigned long l,Time=time(NULL);
+ unsigned long l,Time=(unsigned long)time(NULL);
void (*cb)(const SSL *ssl,int type,int val)=NULL;
long num1;
int ret= -1;
s->shutdown=0;
ret=ssl3_get_client_hello(s);
if (ret <= 0) goto end;
+
s->new_session = 2;
s->state=SSL3_ST_SW_SRVR_HELLO_A;
s->init_num=0;
if (ret == 2)
s->state = SSL3_ST_SR_CLNT_HELLO_C;
else {
- /* could be sent for a DH cert, even if we
- * have not asked for it :-) */
- ret=ssl3_get_client_certificate(s);
- if (ret <= 0) goto end;
+ if (s->s3->tmp.cert_request)
+ {
+ ret=ssl3_get_client_certificate(s);
+ if (ret <= 0) goto end;
+ }
s->init_num=0;
s->state=SSL3_ST_SR_KEY_EXCH_A;
}
return(ret);
}
-static int ssl3_send_hello_request(SSL *s)
+int ssl3_send_hello_request(SSL *s)
{
unsigned char *p;
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,
return 1;
}
-static int ssl3_get_client_hello(SSL *s)
+int ssl3_get_client_hello(SSL *s)
{
int i,j,ok,al,ret= -1;
+ unsigned int cookie_len;
long n;
unsigned long id;
unsigned char *p,*d,*q;
SSL_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
SSL_COMP *comp=NULL;
+#endif
STACK_OF(SSL_CIPHER) *ciphers=NULL;
/* We do this so that we will respond with our native type.
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,
}
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))
{
if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
{
/* Very bad for multi-threading.... */
- s->session->cipher=sk_SSL_CIPHER_value(ciphers,
- 0);
+ s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0);
}
else
{
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions*/
+ if (s->version > SSL3_VERSION)
+ {
+ if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
+ {
+ /* 'al' set by ssl_parse_clienthello_tlsext */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLS_EXT);
+ goto f_err;
+ }
+ }
+ if (ssl_check_tlsext(s,1) <= 0) {
+ SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLS_EXT);
+ goto err;
+ }
+#endif
+
/* 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. */
s->s3->tmp.new_compression=NULL;
- if (s->ctx->comp_methods != NULL)
+#ifndef OPENSSL_NO_COMP
+ if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
{ /* See if we have a match */
int m,nn,o,v,done=0;
else
comp=NULL;
}
-
- /* TLS does not mind if there is extra stuff */
- if (s->version == SSL3_VERSION)
- {
- if (p < (d+n))
- {
- /* wrong number of bytes,
- * there could be more to follow */
- al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
- 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
s->session->compress_meth=(comp == NULL)?0:comp->id;
+#endif
if (s->session->ciphers != NULL)
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers=ciphers;
return(ret);
}
-static int ssl3_send_server_hello(SSL *s)
+int ssl3_send_server_hello(SSL *s)
{
unsigned char *buf;
unsigned char *p,*d;
{
buf=(unsigned char *)s->init_buf->data;
p=s->s3->server_random;
- Time=time(NULL); /* Time */
+ Time=(unsigned long)time(NULL); /* Time */
l2n(Time,p);
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+ if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ return -1;
/* Do the message type and length last */
d=p= &(buf[4]);
s->session->session_id_length=0;
sl=s->session->session_id_length;
- if (sl > sizeof s->session->session_id)
+ if (sl > (int)sizeof(s->session->session_id))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
return -1;
p+=i;
/* put the compression method */
+#ifdef OPENSSL_NO_COMP
+ *(p++)=0;
+#else
if (s->s3->tmp.new_compression == NULL)
*(p++)=0;
else
*(p++)=s->s3->tmp.new_compression->id;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+ if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+#endif
/* do the header */
l=(p-d);
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;
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;
#ifndef OPENSSL_NO_ECDH
if (type & SSL_kECDHE)
{
+ const EC_GROUP *group;
+
ecdhp=cert->ecdh_tmp;
if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
{
}
if (!EC_KEY_up_ref(ecdhp))
{
- SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB);
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
goto err;
}
ecdh = ecdhp;
s->s3->tmp.ecdh=ecdh;
- if ((ecdh->pub_key == NULL) ||
- (ecdh->priv_key == NULL) ||
+ if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
+ (EC_KEY_get0_private_key(ecdh) == NULL) ||
(s->options & SSL_OP_SINGLE_ECDH_USE))
{
if(!EC_KEY_generate_key(ecdh))
}
}
- if ((ecdh->group == NULL) ||
- (ecdh->pub_key == NULL) ||
- (ecdh->priv_key == NULL))
+ if (((group = EC_KEY_get0_group(ecdh)) == NULL) ||
+ (EC_KEY_get0_public_key(ecdh) == NULL) ||
+ (EC_KEY_get0_private_key(ecdh) == NULL))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
goto err;
}
if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
- (EC_GROUP_get_degree(ecdh->group) > 163))
+ (EC_GROUP_get_degree(group) > 163))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER);
goto err;
* supported named curves, curve_id is non-zero.
*/
if ((curve_id =
- nid2curve_id(EC_GROUP_get_nid(ecdh->group)))
+ nid2curve_id(EC_GROUP_get_curve_name(group)))
== 0)
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
* First check the size of encoding and
* allocate memory accordingly.
*/
- encodedlen = EC_POINT_point2oct(ecdh->group,
- ecdh->pub_key,
+ encodedlen = EC_POINT_point2oct(group,
+ EC_KEY_get0_public_key(ecdh),
POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, NULL);
}
- encodedlen = EC_POINT_point2oct(ecdh->group,
- ecdh->pub_key,
+ encodedlen = EC_POINT_point2oct(group,
+ EC_KEY_get0_public_key(ecdh),
POINT_CONVERSION_UNCOMPRESSED,
encodedPoint, encodedlen, bn_ctx);
/* XXX: For now, we only support named (not
* generic) curves in ECDH ephemeral key exchanges.
- * In this situation, we need three additional bytes
+ * In this situation, we need four additional bytes
* to encode the entire ServerECDHParams
* structure.
*/
- n = 3 + encodedlen;
+ n = 4 + encodedlen;
/* We'll generate the serverKeyExchange message
* explicitly so we can set these to NULLs
r[0]=NULL;
r[1]=NULL;
r[2]=NULL;
+ r[3]=NULL;
}
else
#endif /* !OPENSSL_NO_ECDH */
kn=0;
}
- if (!BUF_MEM_grow(buf,n+4+kn))
+ if (!BUF_MEM_grow_clean(buf,n+4+kn))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
goto err;
{
/* 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 CurveType], [2 byte CurveName]
* [1 byte length of encoded point], followed by
* the actual encoded point itself
*/
*p = NAMED_CURVE_TYPE;
p += 1;
+ *p = 0;
+ p += 1;
*p = curve_id;
p += 1;
*p = encodedlen;
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;
{
name=sk_X509_NAME_value(sk,i);
j=i2d_X509_NAME(name,NULL);
- if (!BUF_MEM_grow(buf,4+n+j+2))
+ if (!BUF_MEM_grow_clean(buf,4+n+j+2))
{
SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
goto err;
s->init_num += 4;
#endif
+ s->state = SSL3_ST_SW_CERT_REQ_B;
}
/* SSL3_ST_SW_CERT_REQ_B */
return(-1);
}
-static int ssl3_get_client_key_exchange(SSL *s)
+int ssl3_get_client_key_exchange(SSL *s)
{
int i,al,ok;
long n;
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,
if (i != SSL_MAX_MASTER_KEY_LENGTH)
{
al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
+ /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
}
if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
(p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
{
al=SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
- goto f_err;
+ /* 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)
{
-#if 0
- goto f_err;
-#else
/* 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).
- * But note that due to length and protocol version checking, the
- * attack is impractical anyway (see section 5 in D. Bleichenbacher:
- * "Chosen Ciphertext Attacks Against Protocols Based on the RSA
- * Encryption Standard PKCS #1", CRYPTO '98, LNCS 1462, pp. 1-12).
- */
+ * (see RFC 2246, section 7.4.7.1). */
ERR_clear_error();
i = SSL_MAX_MASTER_KEY_LENGTH;
p[0] = s->client_version >> 8;
p[1] = s->client_version & 0xff;
- RAND_pseudo_bytes(p+2, i-2); /* should be RAND_bytes, but we cannot work around a failure */
-#endif
+ 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->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,
p,i);
- memset(p,0,i);
+ OPENSSL_cleanse(p,i);
}
else
#endif
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,p,i);
- memset(p,0,i);
+ OPENSSL_cleanse(p,i);
}
else
#endif
n2s(p,i);
enc_ticket.length = i;
+
+ if (n < enc_ticket.length + 6)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+
enc_ticket.data = (char *)p;
p+=enc_ticket.length;
n2s(p,i);
authenticator.length = i;
+
+ if (n < enc_ticket.length + authenticator.length + 6)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+
authenticator.data = (char *)p;
p+=authenticator.length;
goto err;
}
- if (n != enc_ticket.length + authenticator.length +
- enc_pms.length + 6)
+ if (n != (long)(enc_ticket.length + authenticator.length +
+ enc_pms.length + 6))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
if (kssl_err.text)
printf("kssl_err text= %s\n", kssl_err.text);
#endif /* KSSL_DEBUG */
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
kssl_err.reason);
goto err;
}
if (kssl_err.text)
printf("kssl_err text= %s\n", kssl_err.text);
#endif /* KSSL_DEBUG */
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
kssl_err.reason);
goto err;
}
if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc);
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
goto err;
}
if (enc == NULL)
goto err;
- memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */
+ memset(iv, 0, sizeof iv); /* per RFC 1510 */
if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
{
if ((l & SSL_kECDH) || (l & SSL_kECDHE))
{
int ret = 1;
+ int field_size = 0;
+ const EC_KEY *tkey;
+ const EC_GROUP *group;
+ const BIGNUM *priv_key;
/* initialize structures for server's ECDH key pair */
if ((srvr_ecdh = EC_KEY_new()) == NULL)
if (l & SSL_kECDH)
{
/* use the certificate */
- srvr_ecdh->group = s->cert->key->privatekey-> \
- pkey.eckey->group;
- srvr_ecdh->priv_key = s->cert->key->privatekey-> \
- pkey.eckey->priv_key;
+ tkey = s->cert->key->privatekey->pkey.ec;
}
else
{
/* use the ephermeral values we saved when
* generating the ServerKeyExchange msg.
*/
- srvr_ecdh->group = s->s3->tmp.ecdh->group;
- srvr_ecdh->priv_key = s->s3->tmp.ecdh->priv_key;
+ tkey = s->s3->tmp.ecdh;
+ }
+
+ group = EC_KEY_get0_group(tkey);
+ priv_key = EC_KEY_get0_private_key(tkey);
+
+ if (!EC_KEY_set_group(srvr_ecdh, group) ||
+ !EC_KEY_set_private_key(srvr_ecdh, priv_key))
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_EC_LIB);
+ goto err;
}
/* Let's get client's public key */
- if ((clnt_ecpoint = EC_POINT_new(srvr_ecdh->group))
- == NULL)
+ if ((clnt_ecpoint = EC_POINT_new(group)) == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto f_err;
}
- EC_POINT_copy(clnt_ecpoint,
- clnt_pub_pkey->pkey.eckey->pub_key);
+ if (EC_POINT_copy(clnt_ecpoint,
+ EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_EC_LIB);
+ goto err;
+ }
ret = 2; /* Skip certificate verify processing */
}
else
/* Get encoded point length */
i = *p;
p += 1;
- if (EC_POINT_oct2point(srvr_ecdh->group,
+ if (EC_POINT_oct2point(group,
clnt_ecpoint, p, i, bn_ctx) == 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
}
/* Compute the shared pre-master secret */
- i = ECDH_compute_key(p, clnt_ecpoint, srvr_ecdh);
+ field_size = EC_GROUP_get_degree(group);
+ if (field_size <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_ECDH_LIB);
+ goto err;
+ }
+ i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
if (srvr_ecdh != NULL)
- {
- srvr_ecdh->priv_key = NULL;
- srvr_ecdh->group = NULL;
EC_KEY_free(srvr_ecdh);
- }
BN_CTX_free(bn_ctx);
/* Compute the master secret */
s->session->master_key_length = s->method->ssl3_enc-> \
generate_master_secret(s, s->session->master_key, p, i);
- memset(p, 0, i);
+ OPENSSL_cleanse(p, i);
return (ret);
}
else
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
err:
#endif
-#ifndef NO_OPENSSL_ECDH
+#ifndef OPENSSL_NO_ECDH
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
if (srvr_ecdh != NULL)
- {
- srvr_ecdh->priv_key = NULL;
- srvr_ecdh->group = NULL;
EC_KEY_free(srvr_ecdh);
- }
BN_CTX_free(bn_ctx);
#endif
return(-1);
}
-static int ssl3_get_cert_verify(SSL *s)
+int ssl3_get_cert_verify(SSL *s)
{
EVP_PKEY *pkey=NULL;
unsigned char *p;
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,
{
j=ECDSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
- SHA_DIGEST_LENGTH,p,i,pkey->pkey.eckey);
+ SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec);
if (j <= 0)
{
/* bad signature */
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;
unsigned long l,nc,llen,n;
- unsigned char *p,*d,*q;
+ const unsigned char *p,*q;
+ 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,
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
goto f_err;
}
- d=p=(unsigned char *)s->init_msg;
+ p=d=(unsigned char *)s->init_msg;
if ((sk=sk_X509_new_null()) == NULL)
{
/* 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) */
+ /* 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;