summaryrefslogtreecommitdiffstats
path: root/crypto/openssl/ssl/ssl_lib.c
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2012-07-12 19:30:53 +0000
committerjkim <jkim@FreeBSD.org>2012-07-12 19:30:53 +0000
commite393e47b1e23744a7d0ed999afb5d137070f5f8f (patch)
tree9739a803477c4610ec6628d914bdcc55fbb3602a /crypto/openssl/ssl/ssl_lib.c
parenta8b00dea2cde4c3d96e6ed1de530ddff21012266 (diff)
parent532b4084cb8cac5e6d91d42aa6a497dd4ba4a4f5 (diff)
downloadFreeBSD-src-e393e47b1e23744a7d0ed999afb5d137070f5f8f.zip
FreeBSD-src-e393e47b1e23744a7d0ed999afb5d137070f5f8f.tar.gz
Merge OpenSSL 1.0.1c.
Approved by: benl (maintainer)
Diffstat (limited to 'crypto/openssl/ssl/ssl_lib.c')
-rw-r--r--crypto/openssl/ssl/ssl_lib.c764
1 files changed, 625 insertions, 139 deletions
diff --git a/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c
index 23de315..f82d071 100644
--- a/crypto/openssl/ssl/ssl_lib.c
+++ b/crypto/openssl/ssl/ssl_lib.c
@@ -58,7 +58,7 @@
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2001 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
@@ -115,6 +115,32 @@
* ECC cipher suite support in OpenSSL originally developed by
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
*/
+/* ====================================================================
+ * 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.
+ */
#ifdef REF_CHECK
# include <assert.h>
@@ -143,14 +169,17 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={
ssl_undefined_function,
(int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function,
(int (*)(SSL*, int))ssl_undefined_function,
- (int (*)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char*, int, unsigned char *))ssl_undefined_function,
+ (int (*)(SSL *, const char*, int, unsigned char *))ssl_undefined_function,
0, /* finish_mac_length */
- (int (*)(SSL *, EVP_MD_CTX *, unsigned char *))ssl_undefined_function,
+ (int (*)(SSL *, int, unsigned char *))ssl_undefined_function,
NULL, /* client_finished_label */
0, /* client_finished_label_len */
NULL, /* server_finished_label */
0, /* server_finished_label_len */
- (int (*)(int))ssl_undefined_function
+ (int (*)(int))ssl_undefined_function,
+ (int (*)(SSL *, unsigned char *, size_t, const char *,
+ size_t, const unsigned char *, size_t,
+ int use_context)) ssl_undefined_function,
};
int SSL_clear(SSL *s)
@@ -176,9 +205,9 @@ int SSL_clear(SSL *s)
* needed because SSL_clear is not called when doing renegotiation) */
/* This is set if we are doing dynamic renegotiation so keep
* the old cipher. It is sort of a SSL_clear_lite :-) */
- if (s->new_session) return(1);
+ if (s->renegotiate) return(1);
#else
- if (s->new_session)
+ if (s->renegotiate)
{
SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR);
return 0;
@@ -204,6 +233,8 @@ int SSL_clear(SSL *s)
}
ssl_clear_cipher_ctx(s);
+ ssl_clear_hash_ctx(&s->read_hash);
+ ssl_clear_hash_ctx(&s->write_hash);
s->first_packet=0;
@@ -224,14 +255,15 @@ int SSL_clear(SSL *s)
}
/** Used to change an SSL_CTXs default SSL method type */
-int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth)
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth)
{
STACK_OF(SSL_CIPHER) *sk;
ctx->method=meth;
sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
- &(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST);
+ &(ctx->cipher_list_by_id),
+ meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
{
SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
@@ -308,6 +340,7 @@ SSL *SSL_new(SSL_CTX *ctx)
s->trust = ctx->trust;
#endif
s->quiet_shutdown=ctx->quiet_shutdown;
+ s->max_send_fragment = ctx->max_send_fragment;
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->ctx=ctx;
@@ -323,7 +356,11 @@ SSL *SSL_new(SSL_CTX *ctx)
s->tlsext_ocsp_resplen = -1;
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->initial_ctx=ctx;
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ s->next_proto_negotiated = NULL;
+# endif
#endif
+
s->verify_result=X509_V_OK;
s->method=ctx->method;
@@ -338,6 +375,11 @@ SSL *SSL_new(SSL_CTX *ctx)
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
+#ifndef OPENSSL_NO_PSK
+ s->psk_client_callback=ctx->psk_client_callback;
+ s->psk_server_callback=ctx->psk_server_callback;
+#endif
+
return(s);
err:
if (s != NULL)
@@ -425,7 +467,7 @@ int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
}
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
- p = (SSL_SESSION *)lh_retrieve(ssl->ctx->sessions, &r);
+ p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r);
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
return (p != NULL);
}
@@ -450,6 +492,16 @@ int SSL_set_trust(SSL *s, int trust)
return X509_VERIFY_PARAM_set_trust(s->param, trust);
}
+int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
+ {
+ return X509_VERIFY_PARAM_set1(ctx->param, vpm);
+ }
+
+int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
+ {
+ return X509_VERIFY_PARAM_set1(ssl->param, vpm);
+ }
+
void SSL_free(SSL *s)
{
int i;
@@ -504,6 +556,8 @@ void SSL_free(SSL *s)
}
ssl_clear_cipher_ctx(s);
+ ssl_clear_hash_ctx(&s->read_hash);
+ ssl_clear_hash_ctx(&s->write_hash);
if (s->cert != NULL) ssl_cert_free(s->cert);
/* Free up if allocated */
@@ -512,6 +566,11 @@ void SSL_free(SSL *s)
if (s->tlsext_hostname)
OPENSSL_free(s->tlsext_hostname);
if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+#ifndef OPENSSL_NO_EC
+ if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist);
+ if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+ if (s->tlsext_opaque_prf_input) OPENSSL_free(s->tlsext_opaque_prf_input);
if (s->tlsext_ocsp_exts)
sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
X509_EXTENSION_free);
@@ -520,6 +579,7 @@ void SSL_free(SSL *s)
if (s->tlsext_ocsp_resp)
OPENSSL_free(s->tlsext_ocsp_resp);
#endif
+
if (s->client_CA != NULL)
sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
@@ -532,6 +592,14 @@ void SSL_free(SSL *s)
kssl_ctx_free(s->kssl_ctx);
#endif /* OPENSSL_NO_KRB5 */
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+ if (s->next_proto_negotiated)
+ OPENSSL_free(s->next_proto_negotiated);
+#endif
+
+ if (s->srtp_profiles)
+ sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
+
OPENSSL_free(s);
}
@@ -844,7 +912,7 @@ int SSL_check_private_key(const SSL *ssl)
}
if (ssl->cert == NULL)
{
- SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
+ SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
if (ssl->cert->key->x509 == NULL)
@@ -954,10 +1022,21 @@ int SSL_shutdown(SSL *s)
int SSL_renegotiate(SSL *s)
{
- if (s->new_session == 0)
- {
- s->new_session=1;
- }
+ if (s->renegotiate == 0)
+ s->renegotiate=1;
+
+ s->new_session=1;
+
+ return(s->method->ssl_renegotiate(s));
+ }
+
+int SSL_renegotiate_abbreviated(SSL *s)
+ {
+ if (s->renegotiate == 0)
+ s->renegotiate=1;
+
+ s->new_session=0;
+
return(s->method->ssl_renegotiate(s));
}
@@ -965,7 +1044,7 @@ int SSL_renegotiate_pending(SSL *s)
{
/* becomes true when negotiation is requested;
* false again once a handshake has finished */
- return (s->new_session != 0);
+ return (s->renegotiate != 0);
}
long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
@@ -1012,6 +1091,11 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
return larg;
}
return 0;
+ case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+ if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+ s->max_send_fragment = larg;
+ return 1;
case SSL_CTRL_GET_RI_SUPPORT:
if (s->s3)
return s->s3->send_connection_binding;
@@ -1034,7 +1118,7 @@ long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
}
}
-struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx)
+LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
{
return ctx->sessions;
}
@@ -1077,7 +1161,7 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
return(ctx->session_cache_mode);
case SSL_CTRL_SESS_NUMBER:
- return(ctx->sessions->num_items);
+ return(lh_SSL_SESSION_num_items(ctx->sessions));
case SSL_CTRL_SESS_CONNECT:
return(ctx->stats.sess_connect);
case SSL_CTRL_SESS_CONNECT_GOOD:
@@ -1108,6 +1192,11 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
return(ctx->mode|=larg);
case SSL_CTRL_CLEAR_MODE:
return(ctx->mode&=~larg);
+ case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
+ if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+ ctx->max_send_fragment = larg;
+ return 1;
default:
return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
}
@@ -1212,8 +1301,8 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
/* ssl_create_cipher_list may return an empty stack if it
* was unable to find a cipher matching the given rule string
* (for example if the rule string specifies a cipher which
- * has been disabled). This is not an error as far as
- * ssl_create_cipher_list is concerned, and hence
+ * has been disabled). This is not an error as far as
+ * ssl_create_cipher_list is concerned, and hence
* ctx->cipher_list and ctx->cipher_list_by_id has been
* updated. */
if (sk == NULL)
@@ -1281,13 +1370,13 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
}
int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
- int (*put_cb)(const SSL_CIPHER *, unsigned char *))
+ int (*put_cb)(const SSL_CIPHER *, unsigned char *))
{
int i,j=0;
SSL_CIPHER *c;
unsigned char *q;
#ifndef OPENSSL_NO_KRB5
- int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
+ int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
#endif /* OPENSSL_NO_KRB5 */
if (sk == NULL) return(0);
@@ -1296,22 +1385,32 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
{
c=sk_SSL_CIPHER_value(sk,i);
+ /* Skip TLS v1.2 only ciphersuites if lower than v1.2 */
+ if ((c->algorithm_ssl & SSL_TLSV1_2) &&
+ (TLS1_get_client_version(s) < TLS1_2_VERSION))
+ continue;
#ifndef OPENSSL_NO_KRB5
- if ((c->algorithms & SSL_KRB5) && nokrb5)
- continue;
-#endif /* OPENSSL_NO_KRB5 */
-
+ if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) &&
+ nokrb5)
+ continue;
+#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+ /* with PSK there must be client callback set */
+ if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) &&
+ s->psk_client_callback == NULL)
+ continue;
+#endif /* OPENSSL_NO_PSK */
j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
p+=j;
}
/* If p == q, no ciphers and caller indicates an error. Otherwise
* add SCSV if not renegotiating.
*/
- if (p != q && !s->new_session)
+ if (p != q && !s->renegotiate)
{
static SSL_CIPHER scsv =
{
- 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0,
+ 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
p+=j;
@@ -1326,7 +1425,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
STACK_OF(SSL_CIPHER) **skp)
{
- SSL_CIPHER *c;
+ const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *sk;
int i,n;
if (s->s3)
@@ -1354,7 +1453,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
(p[n-1] == (SSL3_CK_SCSV & 0xff)))
{
/* SCSV fatal if renegotiating */
- if (s->new_session)
+ if (s->renegotiate)
{
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
@@ -1389,6 +1488,7 @@ err:
return(NULL);
}
+
#ifndef OPENSSL_NO_TLSEXT
/** return a servername extension value if provided in Client Hello, or NULL.
* So far, only host_name types are defined (RFC 3546).
@@ -1410,9 +1510,138 @@ int SSL_get_servername_type(const SSL *s)
return TLSEXT_NAMETYPE_host_name;
return -1;
}
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+/* SSL_select_next_proto implements the standard protocol selection. It is
+ * expected that this function is called from the callback set by
+ * SSL_CTX_set_next_proto_select_cb.
+ *
+ * The protocol data is assumed to be a vector of 8-bit, length prefixed byte
+ * strings. The length byte itself is not included in the length. A byte
+ * string of length 0 is invalid. No byte string may be truncated.
+ *
+ * The current, but experimental algorithm for selecting the protocol is:
+ *
+ * 1) If the server doesn't support NPN then this is indicated to the
+ * callback. In this case, the client application has to abort the connection
+ * or have a default application level protocol.
+ *
+ * 2) If the server supports NPN, but advertises an empty list then the
+ * client selects the first protcol in its list, but indicates via the
+ * API that this fallback case was enacted.
+ *
+ * 3) Otherwise, the client finds the first protocol in the server's list
+ * that it supports and selects this protocol. This is because it's
+ * assumed that the server has better information about which protocol
+ * a client should use.
+ *
+ * 4) If the client doesn't support any of the server's advertised
+ * protocols, then this is treated the same as case 2.
+ *
+ * It returns either
+ * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or
+ * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached.
+ */
+int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
+ {
+ unsigned int i, j;
+ const unsigned char *result;
+ int status = OPENSSL_NPN_UNSUPPORTED;
+
+ /* For each protocol in server preference order, see if we support it. */
+ for (i = 0; i < server_len; )
+ {
+ for (j = 0; j < client_len; )
+ {
+ if (server[i] == client[j] &&
+ memcmp(&server[i+1], &client[j+1], server[i]) == 0)
+ {
+ /* We found a match */
+ result = &server[i];
+ status = OPENSSL_NPN_NEGOTIATED;
+ goto found;
+ }
+ j += client[j];
+ j++;
+ }
+ i += server[i];
+ i++;
+ }
+
+ /* There's no overlap between our protocols and the server's list. */
+ result = client;
+ status = OPENSSL_NPN_NO_OVERLAP;
+
+ found:
+ *out = (unsigned char *) result + 1;
+ *outlen = result[0];
+ return status;
+ }
+
+/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's
+ * requested protocol for this connection and returns 0. If the client didn't
+ * request any protocol, then *data is set to NULL.
+ *
+ * Note that the client can request any protocol it chooses. The value returned
+ * from this function need not be a member of the list of supported protocols
+ * provided by the callback.
+ */
+void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+ {
+ *data = s->next_proto_negotiated;
+ if (!*data) {
+ *len = 0;
+ } else {
+ *len = s->next_proto_negotiated_len;
+ }
+}
+
+/* SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a
+ * TLS server needs a list of supported protocols for Next Protocol
+ * Negotiation. The returned list must be in wire format. The list is returned
+ * by setting |out| to point to it and |outlen| to its length. This memory will
+ * not be modified, but one should assume that the SSL* keeps a reference to
+ * it.
+ *
+ * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. Otherwise, no
+ * such extension will be included in the ServerHello. */
+void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg)
+ {
+ ctx->next_protos_advertised_cb = cb;
+ ctx->next_protos_advertised_cb_arg = arg;
+ }
+
+/* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a
+ * client needs to select a protocol from the server's provided list. |out|
+ * must be set to point to the selected protocol (which may be within |in|).
+ * The length of the protocol name must be written into |outlen|. The server's
+ * advertised protocols are provided in |in| and |inlen|. The callback can
+ * assume that |in| is syntactically valid.
+ *
+ * The client must select a protocol. It is fatal to the connection if this
+ * callback returns a value other than SSL_TLSEXT_ERR_OK.
+ */
+void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
+ {
+ ctx->next_proto_select_cb = cb;
+ ctx->next_proto_select_cb_arg = arg;
+ }
+# endif
#endif
-unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
+int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen, const unsigned char *p, size_t plen,
+ int use_context)
+ {
+ if (s->version < TLS1_VERSION)
+ return -1;
+
+ return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
+ llen, p, plen,
+ use_context);
+ }
+
+static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
unsigned long l;
@@ -1429,7 +1658,7 @@ unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
* SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being
* able to construct an SSL_SESSION that will collide with any existing session
* with a matching session ID. */
-int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
+static int ssl_session_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
{
if (a->ssl_version != b->ssl_version)
return(1);
@@ -1442,13 +1671,13 @@ int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
* SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each
* variable. The reason is that the functions aren't static, they're exposed via
* ssl.h. */
-static IMPLEMENT_LHASH_HASH_FN(SSL_SESSION_hash, SSL_SESSION *)
-static IMPLEMENT_LHASH_COMP_FN(SSL_SESSION_cmp, SSL_SESSION *)
+static IMPLEMENT_LHASH_HASH_FN(ssl_session, SSL_SESSION)
+static IMPLEMENT_LHASH_COMP_FN(ssl_session, SSL_SESSION)
-SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
+SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
{
SSL_CTX *ret=NULL;
-
+
if (meth == NULL)
{
SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED);
@@ -1525,15 +1754,14 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
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));
+ ret->sessions=lh_SSL_SESSION_new();
if (ret->sessions == NULL) goto err;
ret->cert_store=X509_STORE_new();
if (ret->cert_store == NULL) goto err;
ssl_create_cipher_list(ret->method,
&ret->cipher_list,&ret->cipher_list_by_id,
- SSL_DEFAULT_CIPHER_LIST);
+ meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST);
if (ret->cipher_list == NULL
|| sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
{
@@ -1569,6 +1797,8 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
ret->extra_certs=NULL;
ret->comp_methods=SSL_COMP_get_compression_methods();
+ ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
+
#ifndef OPENSSL_NO_TLSEXT
ret->tlsext_servername_callback = 0;
ret->tlsext_servername_arg = NULL;
@@ -1581,8 +1811,37 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
ret->tlsext_status_cb = 0;
ret->tlsext_status_arg = NULL;
+# ifndef OPENSSL_NO_NEXTPROTONEG
+ ret->next_protos_advertised_cb = 0;
+ ret->next_proto_select_cb = 0;
+# endif
+#endif
+#ifndef OPENSSL_NO_PSK
+ ret->psk_identity_hint=NULL;
+ ret->psk_client_callback=NULL;
+ ret->psk_server_callback=NULL;
+#endif
+#ifndef OPENSSL_NO_SRP
+ SSL_CTX_SRP_CTX_init(ret);
+#endif
+#ifndef OPENSSL_NO_BUF_FREELISTS
+ ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT;
+ ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+ if (!ret->rbuf_freelist)
+ goto err;
+ ret->rbuf_freelist->chunklen = 0;
+ ret->rbuf_freelist->len = 0;
+ ret->rbuf_freelist->head = NULL;
+ ret->wbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST));
+ if (!ret->wbuf_freelist)
+ {
+ OPENSSL_free(ret->rbuf_freelist);
+ goto err;
+ }
+ ret->wbuf_freelist->chunklen = 0;
+ ret->wbuf_freelist->len = 0;
+ ret->wbuf_freelist->head = NULL;
#endif
-
#ifndef OPENSSL_NO_ENGINE
ret->client_cert_engine = NULL;
#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
@@ -1621,6 +1880,20 @@ static void SSL_COMP_free(SSL_COMP *comp)
{ OPENSSL_free(comp); }
#endif
+#ifndef OPENSSL_NO_BUF_FREELISTS
+static void
+ssl_buf_freelist_free(SSL3_BUF_FREELIST *list)
+ {
+ SSL3_BUF_FREELIST_ENTRY *ent, *next;
+ for (ent = list->head; ent; ent = next)
+ {
+ next = ent->next;
+ OPENSSL_free(ent);
+ }
+ OPENSSL_free(list);
+ }
+#endif
+
void SSL_CTX_free(SSL_CTX *a)
{
int i;
@@ -1658,7 +1931,7 @@ void SSL_CTX_free(SSL_CTX *a)
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
if (a->sessions != NULL)
- lh_free(a->sessions);
+ lh_SSL_SESSION_free(a->sessions);
if (a->cert_store != NULL)
X509_STORE_free(a->cert_store);
@@ -1678,10 +1951,29 @@ void SSL_CTX_free(SSL_CTX *a)
#else
a->comp_methods = NULL;
#endif
+
+ if (a->srtp_profiles)
+ sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
+
+#ifndef OPENSSL_NO_PSK
+ if (a->psk_identity_hint)
+ OPENSSL_free(a->psk_identity_hint);
+#endif
+#ifndef OPENSSL_NO_SRP
+ SSL_CTX_SRP_CTX_free(a);
+#endif
#ifndef OPENSSL_NO_ENGINE
if (a->client_cert_engine)
ENGINE_finish(a->client_cert_engine);
#endif
+
+#ifndef OPENSSL_NO_BUF_FREELISTS
+ if (a->wbuf_freelist)
+ ssl_buf_freelist_free(a->wbuf_freelist);
+ if (a->rbuf_freelist)
+ ssl_buf_freelist_free(a->rbuf_freelist);
+#endif
+
OPENSSL_free(a);
}
@@ -1712,20 +2004,20 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth)
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
-void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
+void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
{
CERT_PKEY *cpk;
int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign;
int rsa_enc_export,dh_rsa_export,dh_dsa_export;
int rsa_tmp_export,dh_tmp_export,kl;
- unsigned long mask,emask;
+ unsigned long mask_k,mask_a,emask_k,emask_a;
int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;
#ifndef OPENSSL_NO_ECDH
int have_ecdh_tmp;
#endif
X509 *x = NULL;
EVP_PKEY *ecc_pkey = NULL;
- int signature_nid = 0;
+ int signature_nid = 0, pk_nid = 0, md_nid = 0;
if (c == NULL) return;
@@ -1765,60 +2057,77 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl);
cpk= &(c->pkeys[SSL_PKEY_ECC]);
have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL);
- mask=0;
- emask=0;
+ mask_k=0;
+ mask_a=0;
+ emask_k=0;
+ emask_a=0;
+
+
#ifdef CIPHER_DEBUG
- printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
- rsa_tmp,rsa_tmp_export,dh_tmp,
+ printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
+ rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
#endif
+
+ cpk = &(c->pkeys[SSL_PKEY_GOST01]);
+ if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST01;
+ }
+ cpk = &(c->pkeys[SSL_PKEY_GOST94]);
+ if (cpk->x509 != NULL && cpk->privatekey !=NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST94;
+ }
if (rsa_enc || (rsa_tmp && rsa_sign))
- mask|=SSL_kRSA;
+ mask_k|=SSL_kRSA;
if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc)))
- emask|=SSL_kRSA;
+ emask_k|=SSL_kRSA;
#if 0
/* The match needs to be both kEDH and aRSA or aDSA, so don't worry */
- if ( (dh_tmp || dh_rsa || dh_dsa) &&
+ if ( (dh_tmp || dh_rsa || dh_dsa) &&
(rsa_enc || rsa_sign || dsa_sign))
- mask|=SSL_kEDH;
+ mask_k|=SSL_kEDH;
if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) &&
(rsa_enc || rsa_sign || dsa_sign))
- emask|=SSL_kEDH;
+ emask_k|=SSL_kEDH;
#endif
- if (dh_tmp_export)
- emask|=SSL_kEDH;
+ if (dh_tmp_export)
+ emask_k|=SSL_kEDH;
if (dh_tmp)
- mask|=SSL_kEDH;
+ mask_k|=SSL_kEDH;
- if (dh_rsa) mask|=SSL_kDHr;
- if (dh_rsa_export) emask|=SSL_kDHr;
+ if (dh_rsa) mask_k|=SSL_kDHr;
+ if (dh_rsa_export) emask_k|=SSL_kDHr;
- if (dh_dsa) mask|=SSL_kDHd;
- if (dh_dsa_export) emask|=SSL_kDHd;
+ if (dh_dsa) mask_k|=SSL_kDHd;
+ if (dh_dsa_export) emask_k|=SSL_kDHd;
if (rsa_enc || rsa_sign)
{
- mask|=SSL_aRSA;
- emask|=SSL_aRSA;
+ mask_a|=SSL_aRSA;
+ emask_a|=SSL_aRSA;
}
if (dsa_sign)
{
- mask|=SSL_aDSS;
- emask|=SSL_aDSS;
+ mask_a|=SSL_aDSS;
+ emask_a|=SSL_aDSS;
}
- mask|=SSL_aNULL;
- emask|=SSL_aNULL;
+ mask_a|=SSL_aNULL;
+ emask_a|=SSL_aNULL;
#ifndef OPENSSL_NO_KRB5
- mask|=SSL_kKRB5|SSL_aKRB5;
- emask|=SSL_kKRB5|SSL_aKRB5;
+ mask_k|=SSL_kKRB5;
+ mask_a|=SSL_aKRB5;
+ emask_k|=SSL_kKRB5;
+ emask_a|=SSL_aKRB5;
#endif
/* An ECC certificate may be usable for ECDH and/or
@@ -1826,7 +2135,7 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
*/
if (have_ecc_cert)
{
- /* This call populates extension flags (ex_flags) */
+ /* This call populates extension flags (ex_flags) */
x = (c->pkeys[SSL_PKEY_ECC]).x509;
X509_check_purpose(x, -1, 0);
ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
@@ -1834,35 +2143,46 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ?
(x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
ecc_pkey = X509_get_pubkey(x);
- ecc_pkey_size = (ecc_pkey != NULL) ?
+ ecc_pkey_size = (ecc_pkey != NULL) ?
EVP_PKEY_bits(ecc_pkey) : 0;
EVP_PKEY_free(ecc_pkey);
if ((x->sig_alg) && (x->sig_alg->algorithm))
+ {
signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
+ OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid);
+ }
#ifndef OPENSSL_NO_ECDH
if (ecdh_ok)
{
- if ((signature_nid == NID_md5WithRSAEncryption) ||
- (signature_nid == NID_md4WithRSAEncryption) ||
- (signature_nid == NID_md2WithRSAEncryption))
+
+ if (pk_nid == NID_rsaEncryption || pk_nid == NID_rsa)
{
- mask|=SSL_kECDH|SSL_aRSA;
+ mask_k|=SSL_kECDHr;
+ mask_a|=SSL_aECDH;
if (ecc_pkey_size <= 163)
- emask|=SSL_kECDH|SSL_aRSA;
+ {
+ emask_k|=SSL_kECDHr;
+ emask_a|=SSL_aECDH;
+ }
}
- if (signature_nid == NID_ecdsa_with_SHA1)
+
+ if (pk_nid == NID_X9_62_id_ecPublicKey)
{
- mask|=SSL_kECDH|SSL_aECDSA;
+ mask_k|=SSL_kECDHe;
+ mask_a|=SSL_aECDH;
if (ecc_pkey_size <= 163)
- emask|=SSL_kECDH|SSL_aECDSA;
+ {
+ emask_k|=SSL_kECDHe;
+ emask_a|=SSL_aECDH;
+ }
}
}
#endif
#ifndef OPENSSL_NO_ECDSA
if (ecdsa_ok)
{
- mask|=SSL_aECDSA;
- emask|=SSL_aECDSA;
+ mask_a|=SSL_aECDSA;
+ emask_a|=SSL_aECDSA;
}
#endif
}
@@ -1870,12 +2190,22 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
#ifndef OPENSSL_NO_ECDH
if (have_ecdh_tmp)
{
- mask|=SSL_kECDHE;
- emask|=SSL_kECDHE;
+ mask_k|=SSL_kEECDH;
+ emask_k|=SSL_kEECDH;
}
#endif
- c->mask=mask;
- c->export_mask=emask;
+
+#ifndef OPENSSL_NO_PSK
+ mask_k |= SSL_kPSK;
+ mask_a |= SSL_aPSK;
+ emask_k |= SSL_kPSK;
+ emask_a |= SSL_aPSK;
+#endif
+
+ c->mask_k=mask_k;
+ c->mask_a=mask_a;
+ c->export_mask_k=emask_k;
+ c->export_mask_a=emask_a;
c->valid=1;
}
@@ -1883,12 +2213,18 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
#define ku_reject(x, usage) \
(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
-int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)
+#ifndef OPENSSL_NO_EC
+
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
{
- unsigned long alg = cs->algorithms;
+ unsigned long alg_k, alg_a;
EVP_PKEY *pkey = NULL;
int keysize = 0;
- int signature_nid = 0;
+ int signature_nid = 0, md_nid = 0, pk_nid = 0;
+ const SSL_CIPHER *cs = s->s3->tmp.new_cipher;
+
+ alg_k = cs->algorithm_mkey;
+ alg_a = cs->algorithm_auth;
if (SSL_C_IS_EXPORT(cs))
{
@@ -1903,38 +2239,44 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)
/* This call populates the ex_flags field correctly */
X509_check_purpose(x, -1, 0);
if ((x->sig_alg) && (x->sig_alg->algorithm))
+ {
signature_nid = OBJ_obj2nid(x->sig_alg->algorithm);
- if (alg & SSL_kECDH)
+ OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid);
+ }
+ if (alg_k & SSL_kECDHe || alg_k & SSL_kECDHr)
{
/* key usage, if present, must allow key agreement */
if (ku_reject(x, X509v3_KU_KEY_AGREEMENT))
{
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
return 0;
}
- if (alg & SSL_aECDSA)
+ if ((alg_k & SSL_kECDHe) && TLS1_get_version(s) < TLS1_2_VERSION)
{
/* signature alg must be ECDSA */
- if (signature_nid != NID_ecdsa_with_SHA1)
+ if (pk_nid != NID_X9_62_id_ecPublicKey)
{
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE);
return 0;
}
}
- if (alg & SSL_aRSA)
+ if ((alg_k & SSL_kECDHr) && TLS1_get_version(s) < TLS1_2_VERSION)
{
/* signature alg must be RSA */
- if ((signature_nid != NID_md5WithRSAEncryption) &&
- (signature_nid != NID_md4WithRSAEncryption) &&
- (signature_nid != NID_md2WithRSAEncryption))
+
+ if (pk_nid != NID_rsaEncryption && pk_nid != NID_rsa)
{
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE);
return 0;
}
}
- }
- else if (alg & SSL_aECDSA)
+ }
+ if (alg_a & SSL_aECDSA)
{
/* key usage, if present, must allow signing */
if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
{
+ SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
return 0;
}
}
@@ -1942,56 +2284,63 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)
return 1; /* all checks are ok */
}
+#endif
+
/* THIS NEEDS CLEANING UP */
X509 *ssl_get_server_send_cert(SSL *s)
{
- unsigned long alg,kalg;
+ unsigned long alg_k,alg_a;
CERT *c;
int i;
c=s->cert;
ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
- alg=s->s3->tmp.new_cipher->algorithms;
- kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
- if (kalg & SSL_kECDH)
+ if (alg_k & (SSL_kECDHr|SSL_kECDHe))
{
- /* we don't need to look at SSL_kECDHE
+ /* we don't need to look at SSL_kEECDH
* since no certificate is needed for
* anon ECDH and for authenticated
- * ECDHE, the check for the auth
+ * EECDH, the check for the auth
* algorithm will set i correctly
* NOTE: For ECDH-RSA, we need an ECC
- * not an RSA cert but for ECDHE-RSA
+ * not an RSA cert but for EECDH-RSA
* we need an RSA cert. Placing the
* checks for SSL_kECDH before RSA
* checks ensures the correct cert is chosen.
*/
i=SSL_PKEY_ECC;
}
- else if (kalg & SSL_aECDSA)
+ else if (alg_a & SSL_aECDSA)
{
i=SSL_PKEY_ECC;
}
- else if (kalg & SSL_kDHr)
+ else if (alg_k & SSL_kDHr)
i=SSL_PKEY_DH_RSA;
- else if (kalg & SSL_kDHd)
+ else if (alg_k & SSL_kDHd)
i=SSL_PKEY_DH_DSA;
- else if (kalg & SSL_aDSS)
+ else if (alg_a & SSL_aDSS)
i=SSL_PKEY_DSA_SIGN;
- else if (kalg & SSL_aRSA)
+ else if (alg_a & SSL_aRSA)
{
if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
i=SSL_PKEY_RSA_SIGN;
else
i=SSL_PKEY_RSA_ENC;
}
- else if (kalg & SSL_aKRB5)
+ else if (alg_a & SSL_aKRB5)
{
/* VRS something else here? */
return(NULL);
}
- else /* if (kalg & SSL_aNULL) */
+ else if (alg_a & SSL_aGOST94)
+ i=SSL_PKEY_GOST94;
+ else if (alg_a & SSL_aGOST01)
+ i=SSL_PKEY_GOST01;
+ else /* if (alg_a & SSL_aNULL) */
{
SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
return(NULL);
@@ -2001,34 +2350,36 @@ X509 *ssl_get_server_send_cert(SSL *s)
return(c->pkeys[i].x509);
}
-EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher)
+EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
{
- unsigned long alg;
+ unsigned long alg_a;
CERT *c;
+ int idx = -1;
- alg=cipher->algorithms;
+ alg_a = cipher->algorithm_auth;
c=s->cert;
- if ((alg & SSL_aDSS) &&
+ if ((alg_a & SSL_aDSS) &&
(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
- return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
- else if (alg & SSL_aRSA)
+ idx = SSL_PKEY_DSA_SIGN;
+ else if (alg_a & SSL_aRSA)
{
if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
- return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
+ idx = SSL_PKEY_RSA_SIGN;
else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
- return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey);
- else
- return(NULL);
+ idx = SSL_PKEY_RSA_ENC;
}
- else if ((alg & SSL_aECDSA) &&
+ else if ((alg_a & SSL_aECDSA) &&
(c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
- return(c->pkeys[SSL_PKEY_ECC].privatekey);
- else /* if (alg & SSL_aNULL) */
+ idx = SSL_PKEY_ECC;
+ if (idx == -1)
{
SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
return(NULL);
}
+ if (pmd)
+ *pmd = c->pkeys[idx].digest;
+ return c->pkeys[idx].privatekey;
}
void ssl_update_cache(SSL *s,int mode)
@@ -2039,14 +2390,14 @@ void ssl_update_cache(SSL *s,int mode)
* and it would be rather hard to do anyway :-) */
if (s->session->session_id_length == 0) return;
- i=s->ctx->session_cache_mode;
+ i=s->session_ctx->session_cache_mode;
if ((i & mode) && (!s->hit)
&& ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
- || SSL_CTX_add_session(s->ctx,s->session))
- && (s->ctx->new_session_cb != NULL))
+ || SSL_CTX_add_session(s->session_ctx,s->session))
+ && (s->session_ctx->new_session_cb != NULL))
{
CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);
- if (!s->ctx->new_session_cb(s,s->session))
+ if (!s->session_ctx->new_session_cb(s,s->session))
SSL_SESSION_free(s->session);
}
@@ -2055,20 +2406,20 @@ void ssl_update_cache(SSL *s,int mode)
((i & mode) == mode))
{
if ( (((mode & SSL_SESS_CACHE_CLIENT)
- ?s->ctx->stats.sess_connect_good
- :s->ctx->stats.sess_accept_good) & 0xff) == 0xff)
+ ?s->session_ctx->stats.sess_connect_good
+ :s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff)
{
- SSL_CTX_flush_sessions(s->ctx,(unsigned long)time(NULL));
+ SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL));
}
}
}
-SSL_METHOD *SSL_get_ssl_method(SSL *s)
+const SSL_METHOD *SSL_get_ssl_method(SSL *s)
{
return(s->method);
}
-int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth)
+int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
{
int conn= -1;
int ret=1;
@@ -2211,6 +2562,8 @@ void SSL_set_accept_state(SSL *s)
s->handshake_func=s->method->ssl_accept;
/* clear the current cipher */
ssl_clear_cipher_ctx(s);
+ ssl_clear_hash_ctx(&s->read_hash);
+ ssl_clear_hash_ctx(&s->write_hash);
}
void SSL_set_connect_state(SSL *s)
@@ -2221,6 +2574,8 @@ void SSL_set_connect_state(SSL *s)
s->handshake_func=s->method->ssl_connect;
/* clear the current cipher */
ssl_clear_cipher_ctx(s);
+ ssl_clear_hash_ctx(&s->read_hash);
+ ssl_clear_hash_ctx(&s->write_hash);
}
int ssl_undefined_function(SSL *s)
@@ -2249,6 +2604,10 @@ SSL_METHOD *ssl_bad_method(int ver)
const char *SSL_get_version(const SSL *s)
{
+ if (s->version == TLS1_2_VERSION)
+ return("TLSv1.2");
+ else if (s->version == TLS1_1_VERSION)
+ return("TLSv1.1");
if (s->version == TLS1_VERSION)
return("TLSv1");
else if (s->version == SSL3_VERSION)
@@ -2265,7 +2624,7 @@ SSL *SSL_dup(SSL *s)
X509_NAME *xn;
SSL *ret;
int i;
-
+
if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL)
return(NULL);
@@ -2343,6 +2702,7 @@ SSL *SSL_dup(SSL *s)
ret->in_handshake = s->in_handshake;
ret->handshake_func = s->handshake_func;
ret->server = s->server;
+ ret->renegotiate = s->renegotiate;
ret->new_session = s->new_session;
ret->quiet_shutdown = s->quiet_shutdown;
ret->shutdown=s->shutdown;
@@ -2435,7 +2795,7 @@ EVP_PKEY *SSL_get_privatekey(SSL *s)
return(NULL);
}
-SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
+const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
{
if ((s->session != NULL) && (s->session->cipher != NULL))
return(s->session->cipher);
@@ -2513,7 +2873,7 @@ void ssl_free_wbio_buffer(SSL *s)
s->wbio=BIO_pop(s->wbio);
#ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */
assert(s->wbio != NULL);
-#endif
+#endif
}
BIO_free(s->bbio);
s->bbio=NULL;
@@ -2598,7 +2958,7 @@ void SSL_set_info_callback(SSL *ssl,
/* One compiler (Diab DCC) doesn't like argument names in returned
function pointer. */
-void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/)
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/)
{
return ssl->info_callback;
}
@@ -2608,6 +2968,11 @@ int SSL_state(const SSL *ssl)
return(ssl->state);
}
+void SSL_set_state(SSL *ssl, int state)
+ {
+ ssl->state = state;
+ }
+
void SSL_set_verify_result(SSL *ssl,long arg)
{
ssl->verify_result=arg;
@@ -2719,13 +3084,13 @@ RSA *cb(SSL *ssl,int is_export,int keylength)
#ifndef OPENSSL_NO_DH
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export,
- int keylength))
+ int keylength))
{
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
}
void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export,
- int keylength))
+ int keylength))
{
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
}
@@ -2733,18 +3098,109 @@ void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export,
#ifndef OPENSSL_NO_ECDH
void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
- int keylength))
+ int keylength))
{
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
}
void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
- int keylength))
+ int keylength))
{
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
}
#endif
+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+ {
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (ctx->psk_identity_hint != NULL)
+ OPENSSL_free(ctx->psk_identity_hint);
+ if (identity_hint != NULL)
+ {
+ ctx->psk_identity_hint = BUF_strdup(identity_hint);
+ if (ctx->psk_identity_hint == NULL)
+ return 0;
+ }
+ else
+ ctx->psk_identity_hint = NULL;
+ return 1;
+ }
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+ {
+ if (s == NULL)
+ return 0;
+
+ if (s->session == NULL)
+ return 1; /* session not created yet, ignored */
+
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (s->session->psk_identity_hint != NULL)
+ OPENSSL_free(s->session->psk_identity_hint);
+ if (identity_hint != NULL)
+ {
+ s->session->psk_identity_hint = BUF_strdup(identity_hint);
+ if (s->session->psk_identity_hint == NULL)
+ return 0;
+ }
+ else
+ s->session->psk_identity_hint = NULL;
+ return 1;
+ }
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+ {
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return(s->session->psk_identity_hint);
+ }
+
+const char *SSL_get_psk_identity(const SSL *s)
+ {
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return(s->session->psk_identity);
+ }
+
+void SSL_set_psk_client_callback(SSL *s,
+ unsigned int (*cb)(SSL *ssl, const char *hint,
+ char *identity, unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len))
+ {
+ s->psk_client_callback = cb;
+ }
+
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+ unsigned int (*cb)(SSL *ssl, const char *hint,
+ char *identity, unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len))
+ {
+ ctx->psk_client_callback = cb;
+ }
+
+void SSL_set_psk_server_callback(SSL *s,
+ unsigned int (*cb)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len))
+ {
+ s->psk_server_callback = cb;
+ }
+
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+ unsigned int (*cb)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len))
+ {
+ ctx->psk_server_callback = cb;
+ }
+#endif
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))
{
@@ -2755,7 +3211,35 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con
SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
}
+/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * vairable, freeing EVP_MD_CTX previously stored in that variable, if
+ * any. If EVP_MD pointer is passed, initializes ctx with this md
+ * Returns newly allocated ctx;
+ */
+
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md)
+{
+ ssl_clear_hash_ctx(hash);
+ *hash = EVP_MD_CTX_create();
+ if (md) EVP_DigestInit_ex(*hash,md,NULL);
+ return *hash;
+}
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
+{
+
+ if (*hash) EVP_MD_CTX_destroy(*hash);
+ *hash=NULL;
+}
+void SSL_set_debug(SSL *s, int debug)
+ {
+ s->debug = debug;
+ }
+
+int SSL_cache_hit(SSL *s)
+ {
+ return s->hit;
+ }
#if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
#include "../crypto/bio/bss_file.c"
@@ -2763,3 +3247,5 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con
IMPLEMENT_STACK_OF(SSL_CIPHER)
IMPLEMENT_STACK_OF(SSL_COMP)
+IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
+ ssl_cipher_id);
OpenPOWER on IntegriCloud