| Index: openssl/ssl/s3_clnt.c
|
| ===================================================================
|
| --- openssl/ssl/s3_clnt.c (revision 105093)
|
| +++ openssl/ssl/s3_clnt.c (working copy)
|
| @@ -56,7 +56,7 @@
|
| * [including the GNU Public Licence.]
|
| */
|
| /* ====================================================================
|
| - * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
|
| + * Copyright (c) 1998-2007 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
|
| @@ -121,6 +121,32 @@
|
| * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
|
| *
|
| */
|
| +/* ====================================================================
|
| + * Copyright 2005 Nokia. All rights reserved.
|
| + *
|
| + * The portions of the attached software ("Contribution") is developed by
|
| + * Nokia Corporation and is licensed pursuant to the OpenSSL open source
|
| + * license.
|
| + *
|
| + * The Contribution, originally written by Mika Kousa and Pasi Eronen of
|
| + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
|
| + * support (see RFC 4279) to OpenSSL.
|
| + *
|
| + * No patent licenses or other rights except those expressly stated in
|
| + * the OpenSSL open source license shall be deemed granted or received
|
| + * expressly, by implication, estoppel, or otherwise.
|
| + *
|
| + * No assurances are provided by Nokia that the Contribution does not
|
| + * infringe the patent or other intellectual property rights of any third
|
| + * party or that the license provides you with all the necessary rights
|
| + * to make use of the Contribution.
|
| + *
|
| + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
|
| + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
|
| + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
|
| + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
| + * OTHERWISE.
|
| + */
|
|
|
| #include <stdio.h>
|
| #include "ssl_locl.h"
|
| @@ -130,10 +156,6 @@
|
| #include <openssl/objects.h>
|
| #include <openssl/evp.h>
|
| #include <openssl/md5.h>
|
| -#ifdef OPENSSL_FIPS
|
| -#include <openssl/fips.h>
|
| -#endif
|
| -
|
| #ifndef OPENSSL_NO_DH
|
| #include <openssl/dh.h>
|
| #endif
|
| @@ -142,15 +164,10 @@
|
| #include <openssl/engine.h>
|
| #endif
|
|
|
| -static SSL_METHOD *ssl3_get_client_method(int ver);
|
| +static const SSL_METHOD *ssl3_get_client_method(int ver);
|
| static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
|
|
|
| -#ifndef OPENSSL_NO_ECDH
|
| -static int curve_id2nid(int curve_id);
|
| -int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
|
| -#endif
|
| -
|
| -static SSL_METHOD *ssl3_get_client_method(int ver)
|
| +static const SSL_METHOD *ssl3_get_client_method(int ver)
|
| {
|
| if (ver == SSL3_VERSION)
|
| return(SSLv3_client_method());
|
| @@ -166,7 +183,7 @@
|
| int ssl3_connect(SSL *s)
|
| {
|
| BUF_MEM *buf=NULL;
|
| - unsigned long Time=(unsigned long)time(NULL),l;
|
| + unsigned long Time=(unsigned long)time(NULL);
|
| void (*cb)(const SSL *ssl,int type,int val)=NULL;
|
| int ret= -1;
|
| int new_state,state,skip=0;
|
| @@ -182,11 +199,18 @@
|
|
|
| s->in_handshake++;
|
| if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
|
| +#if 0 /* Send app data in separate packet, otherwise, some particular site
|
| + * (only one site so far) closes the socket.
|
| + * Note: there is a very small chance that two TCP packets
|
| + * could be arriving at server combined into a single TCP packet,
|
| + * then trigger that site to break. We haven't encounter that though.
|
| + */
|
| if (SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH)
|
| {
|
| /* Send app data along with CCS/Finished */
|
| s->s3->flags |= SSL3_FLAGS_DELAY_CLIENT_FINISHED;
|
| }
|
| +#endif
|
|
|
| for (;;)
|
| {
|
| @@ -266,6 +290,7 @@
|
| case SSL3_ST_CR_SRVR_HELLO_B:
|
| ret=ssl3_get_server_hello(s);
|
| if (ret <= 0) goto end;
|
| +
|
| if (s->hit)
|
| s->state=SSL3_ST_CR_FINISHED_A;
|
| else
|
| @@ -290,7 +315,9 @@
|
| }
|
| #endif
|
| /* Check if it is anon DH/ECDH */
|
| - if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
|
| + /* or PSK */
|
| + if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
|
| + !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
| {
|
| ret=ssl3_get_server_certificate(s);
|
| if (ret <= 0) goto end;
|
| @@ -365,7 +392,6 @@
|
| case SSL3_ST_CW_KEY_EXCH_B:
|
| ret=ssl3_send_client_key_exchange(s);
|
| if (ret <= 0) goto end;
|
| - l=s->s3->tmp.new_cipher->algorithms;
|
| /* EAY EAY EAY need to check for DH fix cert
|
| * sent back */
|
| /* For TLS, cert_req is set to 2, so a cert chain
|
| @@ -386,6 +412,11 @@
|
| s->state=SSL3_ST_CW_CHANGE_A;
|
| s->s3->change_cipher_spec=0;
|
| }
|
| + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
|
| + {
|
| + s->state=SSL3_ST_CW_CHANGE_A;
|
| + s->s3->change_cipher_spec=0;
|
| + }
|
|
|
| s->init_num=0;
|
| break;
|
| @@ -405,10 +436,15 @@
|
| SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
|
| if (ret <= 0) goto end;
|
|
|
| +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
|
| + s->state=SSL3_ST_CW_FINISHED_A;
|
| +#else
|
| if (s->next_proto_negotiated)
|
| s->state=SSL3_ST_CW_NEXT_PROTO_A;
|
| else
|
| s->state=SSL3_ST_CW_FINISHED_A;
|
| +#endif
|
| +
|
| s->init_num=0;
|
|
|
| s->session->cipher=s->s3->tmp.new_cipher;
|
| @@ -436,12 +472,14 @@
|
|
|
| break;
|
|
|
| +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
| case SSL3_ST_CW_NEXT_PROTO_A:
|
| case SSL3_ST_CW_NEXT_PROTO_B:
|
| ret=ssl3_send_next_proto(s);
|
| if (ret <= 0) goto end;
|
| s->state=SSL3_ST_CW_FINISHED_A;
|
| break;
|
| +#endif
|
|
|
| case SSL3_ST_CW_FINISHED_A:
|
| case SSL3_ST_CW_FINISHED_B:
|
| @@ -648,6 +686,12 @@
|
| #endif
|
| (sess->not_resumable))
|
| {
|
| + if (!s->session_creation_enabled)
|
| + {
|
| + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
|
| + SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
|
| + goto err;
|
| + }
|
| if (!ssl_get_new_session(s,0))
|
| goto err;
|
| }
|
| @@ -701,7 +745,9 @@
|
| #ifdef OPENSSL_NO_COMP
|
| *(p++)=1;
|
| #else
|
| - if (s->ctx->comp_methods == NULL)
|
| +
|
| + if ((s->options & SSL_OP_NO_COMPRESSION)
|
| + || !s->ctx->comp_methods)
|
| j=0;
|
| else
|
| j=sk_SSL_COMP_num(s->ctx->comp_methods);
|
| @@ -713,13 +759,21 @@
|
| }
|
| #endif
|
| *(p++)=0; /* Add the NULL method */
|
| +
|
| #ifndef OPENSSL_NO_TLSEXT
|
| + /* TLS extensions*/
|
| + if (ssl_prepare_clienthello_tlsext(s) <= 0)
|
| + {
|
| + SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
|
| + goto err;
|
| + }
|
| if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
|
| {
|
| SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| }
|
| -#endif
|
| +#endif
|
| +
|
| l=(p-d);
|
| d=buf;
|
| *(d++)=SSL3_MT_CLIENT_HELLO;
|
| @@ -740,7 +794,7 @@
|
| int ssl3_get_server_hello(SSL *s)
|
| {
|
| STACK_OF(SSL_CIPHER) *sk;
|
| - SSL_CIPHER *c;
|
| + const SSL_CIPHER *c;
|
| unsigned char *p,*d;
|
| int i,al,ok;
|
| unsigned int j;
|
| @@ -809,6 +863,23 @@
|
| goto f_err;
|
| }
|
|
|
| +#ifndef OPENSSL_NO_TLSEXT
|
| + /* check if we want to resume the session based on external pre-shared secret */
|
| + if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
|
| + {
|
| + SSL_CIPHER *pref_cipher=NULL;
|
| + s->session->master_key_length=sizeof(s->session->master_key);
|
| + if (s->tls_session_secret_cb(s, s->session->master_key,
|
| + &s->session->master_key_length,
|
| + NULL, &pref_cipher,
|
| + s->tls_session_secret_cb_arg))
|
| + {
|
| + s->session->cipher = pref_cipher ?
|
| + pref_cipher : ssl_get_cipher_by_char(s, p+j);
|
| + }
|
| + }
|
| +#endif /* OPENSSL_NO_TLSEXT */
|
| +
|
| if (j != 0 && j == s->session->session_id_length
|
| && memcmp(p,s->session->session_id,j) == 0)
|
| {
|
| @@ -829,6 +900,12 @@
|
| s->hit=0;
|
| if (s->session->session_id_length > 0)
|
| {
|
| + if (!s->session_creation_enabled)
|
| + {
|
| + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
|
| + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
|
| + goto err;
|
| + }
|
| if (!ssl_get_new_session(s,0))
|
| {
|
| al=SSL_AD_INTERNAL_ERROR;
|
| @@ -866,8 +943,11 @@
|
| s->session->cipher_id = s->session->cipher->id;
|
| if (s->hit && (s->session->cipher_id != c->id))
|
| {
|
| +/* Workaround is now obsolete */
|
| +#if 0
|
| if (!(s->options &
|
| SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG))
|
| +#endif
|
| {
|
| al=SSL_AD_ILLEGAL_PARAMETER;
|
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
|
| @@ -875,6 +955,8 @@
|
| }
|
| }
|
| s->s3->tmp.new_cipher=c;
|
| + if (!ssl3_digest_cached_records(s))
|
| + goto f_err;
|
|
|
| /* lets get the compression algorithm */
|
| /* COMPRESSION */
|
| @@ -885,10 +967,31 @@
|
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
| goto f_err;
|
| }
|
| + /* If compression is disabled we'd better not try to resume a session
|
| + * using compression.
|
| + */
|
| + if (s->session->compress_meth != 0)
|
| + {
|
| + al=SSL_AD_INTERNAL_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
|
| + goto f_err;
|
| + }
|
| #else
|
| j= *(p++);
|
| + if (s->hit && j != s->session->compress_meth)
|
| + {
|
| + al=SSL_AD_ILLEGAL_PARAMETER;
|
| + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
|
| + goto f_err;
|
| + }
|
| if (j == 0)
|
| comp=NULL;
|
| + else if (s->options & SSL_OP_NO_COMPRESSION)
|
| + {
|
| + al=SSL_AD_ILLEGAL_PARAMETER;
|
| + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED);
|
| + goto f_err;
|
| + }
|
| else
|
| comp=ssl3_comp_find(s->ctx->comp_methods,j);
|
|
|
| @@ -903,6 +1006,7 @@
|
| s->s3->tmp.new_compression=comp;
|
| }
|
| #endif
|
| +
|
| #ifndef OPENSSL_NO_TLSEXT
|
| /* TLS extensions*/
|
| if (s->version >= SSL3_VERSION)
|
| @@ -921,13 +1025,12 @@
|
| }
|
| #endif
|
|
|
| -
|
| if (p != (d+n))
|
| {
|
| /* wrong packet length */
|
| al=SSL_AD_DECODE_ERROR;
|
| SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_BAD_PACKET_LENGTH);
|
| - goto err;
|
| + goto f_err;
|
| }
|
|
|
| return(1);
|
| @@ -959,7 +1062,7 @@
|
| if (!ok) return((int)n);
|
|
|
| if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) ||
|
| - ((s->s3->tmp.new_cipher->algorithms & SSL_aKRB5) &&
|
| + ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) &&
|
| (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)))
|
| {
|
| s->s3->tmp.reuse_message=1;
|
| @@ -1024,10 +1127,10 @@
|
| i=ssl_verify_cert_chain(s,sk);
|
| if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
|
| #ifndef OPENSSL_NO_KRB5
|
| - && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK))
|
| - != (SSL_aKRB5|SSL_kKRB5)
|
| + && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
|
| + (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
|
| #endif /* OPENSSL_NO_KRB5 */
|
| - )
|
| + )
|
| {
|
| al=ssl_verify_alarm_type(s->verify_result);
|
| SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
|
| @@ -1051,15 +1154,15 @@
|
| pkey=X509_get_pubkey(x);
|
|
|
| /* VRS: allow null cert if auth == KRB5 */
|
| - need_cert = ((s->s3->tmp.new_cipher->algorithms
|
| - & (SSL_MKEY_MASK|SSL_AUTH_MASK))
|
| - == (SSL_aKRB5|SSL_kKRB5))? 0: 1;
|
| + need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) &&
|
| + (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
|
| + ? 0 : 1;
|
|
|
| #ifdef KSSL_DEBUG
|
| - printf("pkey,x = %p, %p\n", (void *)pkey,(void *)x);
|
| + printf("pkey,x = %p, %p\n", pkey,x);
|
| printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey));
|
| - printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name,
|
| - s->s3->tmp.new_cipher->algorithms, need_cert);
|
| + printf("cipher, alg, nc = %s, %lx, %lx, %d\n", s->s3->tmp.new_cipher->name,
|
| + s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, need_cert);
|
| #endif /* KSSL_DEBUG */
|
|
|
| if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey)))
|
| @@ -1131,7 +1234,7 @@
|
| EVP_MD_CTX md_ctx;
|
| unsigned char *param,*p;
|
| int al,i,j,param_len,ok;
|
| - long n,alg;
|
| + long n,alg_k,alg_a;
|
| EVP_PKEY *pkey=NULL;
|
| #ifndef OPENSSL_NO_RSA
|
| RSA *rsa=NULL;
|
| @@ -1155,17 +1258,28 @@
|
| -1,
|
| s->max_cert_list,
|
| &ok);
|
| -
|
| if (!ok) return((int)n);
|
|
|
| if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
|
| {
|
| +#ifndef OPENSSL_NO_PSK
|
| + /* In plain PSK ciphersuite, ServerKeyExchange can be
|
| + omitted if no identity hint is sent. Set
|
| + session->sess_cert anyway to avoid problems
|
| + later.*/
|
| + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
|
| + {
|
| + s->session->sess_cert=ssl_sess_cert_new();
|
| + if (s->ctx->psk_identity_hint)
|
| + OPENSSL_free(s->ctx->psk_identity_hint);
|
| + s->ctx->psk_identity_hint = NULL;
|
| + }
|
| +#endif
|
| s->s3->tmp.reuse_message=1;
|
| return(1);
|
| }
|
|
|
| param=p=(unsigned char *)s->init_msg;
|
| -
|
| if (s->session->sess_cert != NULL)
|
| {
|
| #ifndef OPENSSL_NO_RSA
|
| @@ -1196,11 +1310,57 @@
|
| }
|
|
|
| param_len=0;
|
| - alg=s->s3->tmp.new_cipher->algorithms;
|
| + alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
| + alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
| EVP_MD_CTX_init(&md_ctx);
|
|
|
| +#ifndef OPENSSL_NO_PSK
|
| + if (alg_k & SSL_kPSK)
|
| + {
|
| + char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
|
| +
|
| + al=SSL_AD_HANDSHAKE_FAILURE;
|
| + n2s(p,i);
|
| + param_len=i+2;
|
| + /* Store PSK identity hint for later use, hint is used
|
| + * in ssl3_send_client_key_exchange. Assume that the
|
| + * maximum length of a PSK identity hint can be as
|
| + * long as the maximum length of a PSK identity. */
|
| + if (i > PSK_MAX_IDENTITY_LEN)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
|
| + SSL_R_DATA_LENGTH_TOO_LONG);
|
| + goto f_err;
|
| + }
|
| + if (param_len > n)
|
| + {
|
| + al=SSL_AD_DECODE_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
|
| + SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
|
| + goto f_err;
|
| + }
|
| + /* If received PSK identity hint contains NULL
|
| + * characters, the hint is truncated from the first
|
| + * NULL. p may not be ending with NULL, so create a
|
| + * NULL-terminated string. */
|
| + memcpy(tmp_id_hint, p, i);
|
| + memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
|
| + if (s->ctx->psk_identity_hint != NULL)
|
| + OPENSSL_free(s->ctx->psk_identity_hint);
|
| + s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
|
| + if (s->ctx->psk_identity_hint == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
|
| + goto f_err;
|
| + }
|
| +
|
| + p+=i;
|
| + n-=param_len;
|
| + }
|
| + else
|
| +#endif /* !OPENSSL_NO_PSK */
|
| #ifndef OPENSSL_NO_RSA
|
| - if (alg & SSL_kRSA)
|
| + if (alg_k & SSL_kRSA)
|
| {
|
| if ((rsa=RSA_new()) == NULL)
|
| {
|
| @@ -1239,7 +1399,7 @@
|
| n-=param_len;
|
|
|
| /* this should be because we are using an export cipher */
|
| - if (alg & SSL_aRSA)
|
| + if (alg_a & SSL_aRSA)
|
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
|
| else
|
| {
|
| @@ -1254,7 +1414,7 @@
|
| ;
|
| #endif
|
| #ifndef OPENSSL_NO_DH
|
| - else if (alg & SSL_kEDH)
|
| + else if (alg_k & SSL_kEDH)
|
| {
|
| if ((dh=DH_new()) == NULL)
|
| {
|
| @@ -1308,14 +1468,14 @@
|
| n-=param_len;
|
|
|
| #ifndef OPENSSL_NO_RSA
|
| - if (alg & SSL_aRSA)
|
| + if (alg_a & SSL_aRSA)
|
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
|
| #else
|
| if (0)
|
| ;
|
| #endif
|
| #ifndef OPENSSL_NO_DSA
|
| - else if (alg & SSL_aDSS)
|
| + else if (alg_a & SSL_aDSS)
|
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
|
| #endif
|
| /* else anonymous DH, so no certificate or pkey. */
|
| @@ -1323,7 +1483,7 @@
|
| s->session->sess_cert->peer_dh_tmp=dh;
|
| dh=NULL;
|
| }
|
| - else if ((alg & SSL_kDHr) || (alg & SSL_kDHd))
|
| + else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd))
|
| {
|
| al=SSL_AD_ILLEGAL_PARAMETER;
|
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
|
| @@ -1332,7 +1492,7 @@
|
| #endif /* !OPENSSL_NO_DH */
|
|
|
| #ifndef OPENSSL_NO_ECDH
|
| - else if (alg & SSL_kECDHE)
|
| + else if (alg_k & SSL_kEECDH)
|
| {
|
| EC_GROUP *ngroup;
|
| const EC_GROUP *group;
|
| @@ -1355,7 +1515,7 @@
|
| param_len=3;
|
| if ((param_len > n) ||
|
| (*p != NAMED_CURVE_TYPE) ||
|
| - ((curve_nid = curve_id2nid(*(p + 2))) == 0))
|
| + ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0))
|
| {
|
| al=SSL_AD_INTERNAL_ERROR;
|
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
| @@ -1416,11 +1576,11 @@
|
| */
|
| if (0) ;
|
| #ifndef OPENSSL_NO_RSA
|
| - else if (alg & SSL_aRSA)
|
| + else if (alg_a & SSL_aRSA)
|
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
|
| #endif
|
| #ifndef OPENSSL_NO_ECDSA
|
| - else if (alg & SSL_aECDSA)
|
| + else if (alg_a & SSL_aECDSA)
|
| pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
|
| #endif
|
| /* else anonymous ECDH, so no certificate or pkey. */
|
| @@ -1428,22 +1588,17 @@
|
| s->session->sess_cert->peer_ecdh_tmp=ecdh;
|
| ecdh=NULL;
|
| BN_CTX_free(bn_ctx);
|
| + bn_ctx = NULL;
|
| EC_POINT_free(srvr_ecpoint);
|
| srvr_ecpoint = NULL;
|
| }
|
| - else if (alg & SSL_kECDH)
|
| + else if (alg_k)
|
| {
|
| al=SSL_AD_UNEXPECTED_MESSAGE;
|
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
|
| goto f_err;
|
| }
|
| #endif /* !OPENSSL_NO_ECDH */
|
| - if (alg & SSL_aFZA)
|
| - {
|
| - al=SSL_AD_HANDSHAKE_FAILURE;
|
| - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
|
| - goto f_err;
|
| - }
|
|
|
|
|
| /* p points to the next byte, there are 'n' bytes left */
|
| @@ -1472,8 +1627,6 @@
|
| q=md_buf;
|
| for (num=2; num > 0; num--)
|
| {
|
| - EVP_MD_CTX_set_flags(&md_ctx,
|
| - EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
| EVP_DigestInit_ex(&md_ctx,(num == 2)
|
| ?s->ctx->md5:s->ctx->sha1, NULL);
|
| EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
| @@ -1544,12 +1697,13 @@
|
| }
|
| else
|
| {
|
| - /* still data left over */
|
| - if (!(alg & SSL_aNULL))
|
| + if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
|
| + /* aNULL or kPSK do not need public keys */
|
| {
|
| SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| }
|
| + /* still data left over */
|
| if (n != 0)
|
| {
|
| al=SSL_AD_DECODE_ERROR;
|
| @@ -1619,8 +1773,7 @@
|
| /* TLS does not like anon-DH with client cert */
|
| if (s->version > SSL3_VERSION)
|
| {
|
| - l=s->s3->tmp.new_cipher->algorithms;
|
| - if (l & SSL_aNULL)
|
| + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
| {
|
| ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
|
| SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
|
| @@ -1761,7 +1914,7 @@
|
| if (n < 6)
|
| {
|
| /* need at least ticket_lifetime_hint + ticket length */
|
| - al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
|
| + al = SSL_AD_DECODE_ERROR;
|
| SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
|
| goto f_err;
|
| }
|
| @@ -1772,7 +1925,7 @@
|
| /* ticket_lifetime_hint + ticket_length + ticket */
|
| if (ticklen + 6 != n)
|
| {
|
| - al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
|
| + al = SSL_AD_DECODE_ERROR;
|
| SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
|
| goto f_err;
|
| }
|
| @@ -1822,8 +1975,7 @@
|
| int ssl3_get_cert_status(SSL *s)
|
| {
|
| int ok, al;
|
| - unsigned long resplen;
|
| - long n;
|
| + unsigned long resplen,n;
|
| const unsigned char *p;
|
|
|
| n=s->method->ssl_get_message(s,
|
| @@ -1849,7 +2001,7 @@
|
| goto f_err;
|
| }
|
| n2l3(p, resplen);
|
| - if (resplen + 4 != (unsigned long)n)
|
| + if (resplen + 4 != n)
|
| {
|
| al = SSL_AD_DECODE_ERROR;
|
| SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
|
| @@ -1918,7 +2070,7 @@
|
| {
|
| unsigned char *p,*d;
|
| int n;
|
| - unsigned long l;
|
| + unsigned long alg_k;
|
| #ifndef OPENSSL_NO_RSA
|
| unsigned char *q;
|
| EVP_PKEY *pkey=NULL;
|
| @@ -1940,12 +2092,12 @@
|
| d=(unsigned char *)s->init_buf->data;
|
| p= &(d[4]);
|
|
|
| - l=s->s3->tmp.new_cipher->algorithms;
|
| + alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
|
| /* Fool emacs indentation */
|
| if (0) {}
|
| #ifndef OPENSSL_NO_RSA
|
| - else if (l & SSL_kRSA)
|
| + else if (alg_k & SSL_kRSA)
|
| {
|
| RSA *rsa;
|
| unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
|
| @@ -2004,7 +2156,7 @@
|
| }
|
| #endif
|
| #ifndef OPENSSL_NO_KRB5
|
| - else if (l & SSL_kKRB5)
|
| + else if (alg_k & SSL_kKRB5)
|
| {
|
| krb5_error_code krb5rc;
|
| KSSL_CTX *kssl_ctx = s->kssl_ctx;
|
| @@ -2012,7 +2164,7 @@
|
| krb5_data *enc_ticket;
|
| krb5_data authenticator, *authp = NULL;
|
| EVP_CIPHER_CTX ciph_ctx;
|
| - EVP_CIPHER *enc = NULL;
|
| + const EVP_CIPHER *enc = NULL;
|
| unsigned char iv[EVP_MAX_IV_LENGTH];
|
| unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
|
| unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH
|
| @@ -2023,7 +2175,7 @@
|
|
|
| #ifdef KSSL_DEBUG
|
| printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
|
| - l, SSL_kKRB5);
|
| + alg_k, SSL_kKRB5);
|
| #endif /* KSSL_DEBUG */
|
|
|
| authp = NULL;
|
| @@ -2115,7 +2267,7 @@
|
| sizeof tmp_buf);
|
| EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl);
|
| outl += padl;
|
| - if (outl > sizeof epms)
|
| + if (outl > (int)sizeof epms)
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| @@ -2129,7 +2281,7 @@
|
| n+=outl + 2;
|
|
|
| s->session->master_key_length=
|
| - s->method->ssl3_enc->generate_master_secret(s,
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| s->session->master_key,
|
| tmp_buf, sizeof tmp_buf);
|
|
|
| @@ -2138,7 +2290,7 @@
|
| }
|
| #endif
|
| #ifndef OPENSSL_NO_DH
|
| - else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| + else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| {
|
| DH *dh_srvr,*dh_clnt;
|
|
|
| @@ -2147,7 +2299,7 @@
|
| ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
|
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
|
| goto err;
|
| - }
|
| + }
|
|
|
| if (s->session->sess_cert->peer_dh_tmp != NULL)
|
| dh_srvr=s->session->sess_cert->peer_dh_tmp;
|
| @@ -2168,6 +2320,7 @@
|
| if (!DH_generate_key(dh_clnt))
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
|
| + DH_free(dh_clnt);
|
| goto err;
|
| }
|
|
|
| @@ -2179,6 +2332,7 @@
|
| if (n <= 0)
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
|
| + DH_free(dh_clnt);
|
| goto err;
|
| }
|
|
|
| @@ -2202,7 +2356,7 @@
|
| #endif
|
|
|
| #ifndef OPENSSL_NO_ECDH
|
| - else if ((l & SSL_kECDH) || (l & SSL_kECDHE))
|
| + else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
|
| {
|
| const EC_GROUP *srvr_group = NULL;
|
| EC_KEY *tkey;
|
| @@ -2214,7 +2368,7 @@
|
| * computation as part of client certificate?
|
| * If so, set ecdh_clnt_cert to 1.
|
| */
|
| - if ((l & SSL_kECDH) && (s->cert != NULL))
|
| + if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL))
|
| {
|
| /* XXX: For now, we do not support client
|
| * authentication using ECDH certificates.
|
| @@ -2386,6 +2540,178 @@
|
| EVP_PKEY_free(srvr_pub_pkey);
|
| }
|
| #endif /* !OPENSSL_NO_ECDH */
|
| + else if (alg_k & SSL_kGOST)
|
| + {
|
| + /* GOST key exchange message creation */
|
| + EVP_PKEY_CTX *pkey_ctx;
|
| + X509 *peer_cert;
|
| + size_t msglen;
|
| + unsigned int md_len;
|
| + int keytype;
|
| + unsigned char premaster_secret[32],shared_ukm[32], tmp[256];
|
| + EVP_MD_CTX *ukm_hash;
|
| + EVP_PKEY *pub_key;
|
| +
|
| + /* Get server sertificate PKEY and create ctx from it */
|
| + peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST01)].x509;
|
| + if (!peer_cert)
|
| + peer_cert=s->session->sess_cert->peer_pkeys[(keytype=SSL_PKEY_GOST94)].x509;
|
| + if (!peer_cert) {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
| + goto err;
|
| + }
|
| +
|
| + pkey_ctx=EVP_PKEY_CTX_new(pub_key=X509_get_pubkey(peer_cert),NULL);
|
| + /* If we have send a certificate, and certificate key
|
| +
|
| + * parameters match those of server certificate, use
|
| + * certificate key for key exchange
|
| + */
|
| +
|
| + /* Otherwise, generate ephemeral key pair */
|
| +
|
| + EVP_PKEY_encrypt_init(pkey_ctx);
|
| + /* Generate session key */
|
| + RAND_bytes(premaster_secret,32);
|
| + /* If we have client certificate, use its secret as peer key */
|
| + if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
|
| + if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
|
| + /* If there was an error - just ignore it. Ephemeral key
|
| + * would be used
|
| + */
|
| + ERR_clear_error();
|
| + }
|
| + }
|
| + /* Compute shared IV and store it in algorithm-specific
|
| + * context data */
|
| + ukm_hash = EVP_MD_CTX_create();
|
| + EVP_DigestInit(ukm_hash,EVP_get_digestbynid(NID_id_GostR3411_94));
|
| + EVP_DigestUpdate(ukm_hash,s->s3->client_random,SSL3_RANDOM_SIZE);
|
| + EVP_DigestUpdate(ukm_hash,s->s3->server_random,SSL3_RANDOM_SIZE);
|
| + EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
|
| + EVP_MD_CTX_destroy(ukm_hash);
|
| + if (EVP_PKEY_CTX_ctrl(pkey_ctx,-1,EVP_PKEY_OP_ENCRYPT,EVP_PKEY_CTRL_SET_IV,
|
| + 8,shared_ukm)<0) {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_LIBRARY_BUG);
|
| + goto err;
|
| + }
|
| + /* Make GOST keytransport blob message */
|
| + /*Encapsulate it into sequence */
|
| + *(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
|
| + msglen=255;
|
| + if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_LIBRARY_BUG);
|
| + goto err;
|
| + }
|
| + if (msglen >= 0x80)
|
| + {
|
| + *(p++)=0x81;
|
| + *(p++)= msglen & 0xff;
|
| + n=msglen+3;
|
| + }
|
| + else
|
| + {
|
| + *(p++)= msglen & 0xff;
|
| + n=msglen+2;
|
| + }
|
| + memcpy(p, tmp, msglen);
|
| + /* Check if pubkey from client certificate was used */
|
| + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
|
| + {
|
| + /* Set flag "skip certificate verify" */
|
| + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
|
| + }
|
| + EVP_PKEY_CTX_free(pkey_ctx);
|
| + s->session->master_key_length=
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| + s->session->master_key,premaster_secret,32);
|
| + EVP_PKEY_free(pub_key);
|
| +
|
| + }
|
| +#ifndef OPENSSL_NO_PSK
|
| + else if (alg_k & SSL_kPSK)
|
| + {
|
| + char identity[PSK_MAX_IDENTITY_LEN];
|
| + unsigned char *t = NULL;
|
| + unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
|
| + unsigned int pre_ms_len = 0, psk_len = 0;
|
| + int psk_err = 1;
|
| +
|
| + n = 0;
|
| + if (s->psk_client_callback == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_PSK_NO_CLIENT_CB);
|
| + goto err;
|
| + }
|
| +
|
| + psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
|
| + identity, PSK_MAX_IDENTITY_LEN,
|
| + psk_or_pre_ms, sizeof(psk_or_pre_ms));
|
| + if (psk_len > PSK_MAX_PSK_LEN)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_INTERNAL_ERROR);
|
| + goto psk_err;
|
| + }
|
| + else if (psk_len == 0)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_PSK_IDENTITY_NOT_FOUND);
|
| + goto psk_err;
|
| + }
|
| +
|
| + /* create PSK pre_master_secret */
|
| + pre_ms_len = 2+psk_len+2+psk_len;
|
| + t = psk_or_pre_ms;
|
| + memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
|
| + s2n(psk_len, t);
|
| + memset(t, 0, psk_len);
|
| + t+=psk_len;
|
| + s2n(psk_len, t);
|
| +
|
| + if (s->session->psk_identity_hint != NULL)
|
| + OPENSSL_free(s->session->psk_identity_hint);
|
| + s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
|
| + if (s->ctx->psk_identity_hint != NULL &&
|
| + s->session->psk_identity_hint == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_MALLOC_FAILURE);
|
| + goto psk_err;
|
| + }
|
| +
|
| + if (s->session->psk_identity != NULL)
|
| + OPENSSL_free(s->session->psk_identity);
|
| + s->session->psk_identity = BUF_strdup(identity);
|
| + if (s->session->psk_identity == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_MALLOC_FAILURE);
|
| + goto psk_err;
|
| + }
|
| +
|
| + s->session->master_key_length =
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| + s->session->master_key,
|
| + psk_or_pre_ms, pre_ms_len);
|
| + n = strlen(identity);
|
| + s2n(n, p);
|
| + memcpy(p, identity, n);
|
| + n+=2;
|
| + psk_err = 0;
|
| + psk_err:
|
| + OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
|
| + OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
|
| + if (psk_err != 0)
|
| + {
|
| + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
| + goto err;
|
| + }
|
| + }
|
| +#endif
|
| else
|
| {
|
| ssl3_send_alert(s, SSL3_AL_FATAL,
|
| @@ -2422,28 +2748,37 @@
|
| unsigned char *p,*d;
|
| unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
|
| EVP_PKEY *pkey;
|
| + EVP_PKEY_CTX *pctx=NULL;
|
| #ifndef OPENSSL_NO_RSA
|
| unsigned u=0;
|
| #endif
|
| unsigned long n;
|
| -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
|
| int j;
|
| -#endif
|
|
|
| if (s->state == SSL3_ST_CW_CERT_VRFY_A)
|
| {
|
| d=(unsigned char *)s->init_buf->data;
|
| p= &(d[4]);
|
| pkey=s->cert->key->privatekey;
|
| -
|
| - s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
|
| - &(data[MD5_DIGEST_LENGTH]));
|
| -
|
| +/* Create context from key and test if sha1 is allowed as digest */
|
| + pctx = EVP_PKEY_CTX_new(pkey,NULL);
|
| + EVP_PKEY_sign_init(pctx);
|
| + if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1())>0)
|
| + {
|
| + s->method->ssl3_enc->cert_verify_mac(s,
|
| + NID_sha1,
|
| + &(data[MD5_DIGEST_LENGTH]));
|
| + }
|
| + else
|
| + {
|
| + ERR_clear_error();
|
| + }
|
| #ifndef OPENSSL_NO_RSA
|
| if (pkey->type == EVP_PKEY_RSA)
|
| {
|
| s->method->ssl3_enc->cert_verify_mac(s,
|
| - &(s->s3->finish_dgst1),&(data[0]));
|
| + NID_md5,
|
| + &(data[0]));
|
| if (RSA_sign(NID_md5_sha1, data,
|
| MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
|
| &(p[2]), &u, pkey->pkey.rsa) <= 0 )
|
| @@ -2489,10 +2824,30 @@
|
| }
|
| else
|
| #endif
|
| - {
|
| + if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
|
| + {
|
| + unsigned char signbuf[64];
|
| + int i;
|
| + size_t sigsize=64;
|
| + s->method->ssl3_enc->cert_verify_mac(s,
|
| + NID_id_GostR3411_94,
|
| + data);
|
| + if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
|
| + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
|
| + ERR_R_INTERNAL_ERROR);
|
| + goto err;
|
| + }
|
| + for (i=63,j=0; i>=0; j++, i--) {
|
| + p[2+j]=signbuf[i];
|
| + }
|
| + s2n(j,p);
|
| + n=j+2;
|
| + }
|
| + else
|
| + {
|
| SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| - }
|
| + }
|
| *(d++)=SSL3_MT_CERTIFICATE_VERIFY;
|
| l2n3(n,d);
|
|
|
| @@ -2500,8 +2855,10 @@
|
| s->init_num=(int)n+4;
|
| s->init_off=0;
|
| }
|
| + EVP_PKEY_CTX_free(pctx);
|
| return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
| err:
|
| + EVP_PKEY_CTX_free(pctx);
|
| return(-1);
|
| }
|
|
|
| @@ -2586,7 +2943,7 @@
|
| int ssl3_check_cert_and_algorithm(SSL *s)
|
| {
|
| int i,idx;
|
| - long algs;
|
| + long alg_k,alg_a;
|
| EVP_PKEY *pkey=NULL;
|
| SESS_CERT *sc;
|
| #ifndef OPENSSL_NO_RSA
|
| @@ -2596,14 +2953,14 @@
|
| DH *dh;
|
| #endif
|
|
|
| - sc=s->session->sess_cert;
|
| + alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
| + alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
|
|
| - algs=s->s3->tmp.new_cipher->algorithms;
|
| -
|
| /* we don't have a certificate */
|
| - if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
|
| + if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
|
| return(1);
|
|
|
| + sc=s->session->sess_cert;
|
| if (sc == NULL)
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
|
| @@ -2623,11 +2980,11 @@
|
| #ifndef OPENSSL_NO_ECDH
|
| if (idx == SSL_PKEY_ECC)
|
| {
|
| - if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
|
| + if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
|
| s->s3->tmp.new_cipher) == 0)
|
| { /* check failed */
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
|
| - goto f_err;
|
| + goto f_err;
|
| }
|
| else
|
| {
|
| @@ -2641,20 +2998,20 @@
|
|
|
|
|
| /* Check that we have a certificate if we require one */
|
| - if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
|
| + if ((alg_a & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT);
|
| goto f_err;
|
| }
|
| #ifndef OPENSSL_NO_DSA
|
| - else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
|
| + else if ((alg_a & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT);
|
| goto f_err;
|
| }
|
| #endif
|
| #ifndef OPENSSL_NO_RSA
|
| - if ((algs & SSL_kRSA) &&
|
| + if ((alg_k & SSL_kRSA) &&
|
| !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
| @@ -2662,19 +3019,19 @@
|
| }
|
| #endif
|
| #ifndef OPENSSL_NO_DH
|
| - if ((algs & SSL_kEDH) &&
|
| + if ((alg_k & SSL_kEDH) &&
|
| !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY);
|
| goto f_err;
|
| }
|
| - else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
|
| + else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT);
|
| goto f_err;
|
| }
|
| #ifndef OPENSSL_NO_DSA
|
| - else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
|
| + else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA))
|
| {
|
| SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT);
|
| goto f_err;
|
| @@ -2685,7 +3042,7 @@
|
| if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
|
| {
|
| #ifndef OPENSSL_NO_RSA
|
| - if (algs & SSL_kRSA)
|
| + if (alg_k & SSL_kRSA)
|
| {
|
| if (rsa == NULL
|
| || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
|
| @@ -2697,7 +3054,7 @@
|
| else
|
| #endif
|
| #ifndef OPENSSL_NO_DH
|
| - if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| + if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| {
|
| if (dh == NULL
|
| || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
|
| @@ -2720,49 +3077,13 @@
|
| return(0);
|
| }
|
|
|
| +/* Check to see if handshake is full or resumed. Usually this is just a
|
| + * case of checking to see if a cache hit has occurred. In the case of
|
| + * session tickets we have to check the next message to be sure.
|
| + */
|
|
|
| -#ifndef OPENSSL_NO_ECDH
|
| -/* This is the complement of nid2curve_id in s3_srvr.c. */
|
| -static int curve_id2nid(int curve_id)
|
| -{
|
| - /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
|
| - * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
|
| - static int nid_list[26] =
|
| - {
|
| - 0,
|
| - NID_sect163k1, /* sect163k1 (1) */
|
| - NID_sect163r1, /* sect163r1 (2) */
|
| - NID_sect163r2, /* sect163r2 (3) */
|
| - NID_sect193r1, /* sect193r1 (4) */
|
| - NID_sect193r2, /* sect193r2 (5) */
|
| - NID_sect233k1, /* sect233k1 (6) */
|
| - NID_sect233r1, /* sect233r1 (7) */
|
| - NID_sect239k1, /* sect239k1 (8) */
|
| - NID_sect283k1, /* sect283k1 (9) */
|
| - NID_sect283r1, /* sect283r1 (10) */
|
| - NID_sect409k1, /* sect409k1 (11) */
|
| - NID_sect409r1, /* sect409r1 (12) */
|
| - NID_sect571k1, /* sect571k1 (13) */
|
| - NID_sect571r1, /* sect571r1 (14) */
|
| - NID_secp160k1, /* secp160k1 (15) */
|
| - NID_secp160r1, /* secp160r1 (16) */
|
| - NID_secp160r2, /* secp160r2 (17) */
|
| - NID_secp192k1, /* secp192k1 (18) */
|
| - NID_X9_62_prime192v1, /* secp192r1 (19) */
|
| - NID_secp224k1, /* secp224k1 (20) */
|
| - NID_secp224r1, /* secp224r1 (21) */
|
| - NID_secp256k1, /* secp256k1 (22) */
|
| - NID_X9_62_prime256v1, /* secp256r1 (23) */
|
| - NID_secp384r1, /* secp384r1 (24) */
|
| - NID_secp521r1 /* secp521r1 (25) */
|
| - };
|
| -
|
| - if ((curve_id < 1) || (curve_id > 25)) return 0;
|
| -
|
| - return nid_list[curve_id];
|
| -}
|
| -#endif
|
| -
|
| +#ifndef OPENSSL_NO_TLSEXT
|
| +# ifndef OPENSSL_NO_NEXTPROTONEG
|
| int ssl3_send_next_proto(SSL *s)
|
| {
|
| unsigned int len, padding_len;
|
| @@ -2785,23 +3106,15 @@
|
| }
|
|
|
| return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
|
| -}
|
| + }
|
| +# endif
|
|
|
| -/* Check to see if handshake is full or resumed. Usually this is just a
|
| - * case of checking to see if a cache hit has occurred. In the case of
|
| - * session tickets we have to check the next message to be sure.
|
| - */
|
| -
|
| -#ifndef OPENSSL_NO_TLSEXT
|
| int ssl3_check_finished(SSL *s)
|
| {
|
| int ok;
|
| long n;
|
| - /* If we have no ticket or session ID is non-zero length (a match of
|
| - * a non-zero session length would never reach here) it cannot be a
|
| - * resumed session.
|
| - */
|
| - if (!s->session->tlsext_tick || s->session->session_id_length)
|
| + /* If we have no ticket it cannot be a resumed session. */
|
| + if (!s->session->tlsext_tick)
|
| return 1;
|
| /* this function is called when we really expect a Certificate
|
| * message, so permit appropriate message length */
|
|
|