| Index: openssl/ssl/ssl_lib.c
|
| ===================================================================
|
| --- openssl/ssl/ssl_lib.c (revision 105093)
|
| +++ openssl/ssl/ssl_lib.c (working copy)
|
| @@ -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,9 +169,9 @@
|
| 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 */
|
| @@ -204,6 +230,8 @@
|
| }
|
|
|
| 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 +252,15 @@
|
| }
|
|
|
| /** 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);
|
| @@ -297,6 +326,7 @@
|
| OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
|
| memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
|
| s->verify_callback=ctx->default_verify_callback;
|
| + s->session_creation_enabled=1;
|
| s->generate_session_id=ctx->generate_session_id;
|
|
|
| s->param = X509_VERIFY_PARAM_new();
|
| @@ -308,6 +338,7 @@
|
| 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,8 +354,11 @@
|
| 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;
|
| @@ -339,6 +373,11 @@
|
|
|
| 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)
|
| @@ -426,7 +465,7 @@
|
| }
|
|
|
| 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);
|
| }
|
| @@ -451,6 +490,16 @@
|
| 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;
|
| @@ -505,6 +554,8 @@
|
| }
|
|
|
| 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 */
|
| @@ -513,6 +564,11 @@
|
| 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);
|
| @@ -521,6 +577,7 @@
|
| 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);
|
|
|
| @@ -533,7 +590,7 @@
|
| kssl_ctx_free(s->kssl_ctx);
|
| #endif /* OPENSSL_NO_KRB5 */
|
|
|
| -#ifndef OPENSSL_NO_TLSEXT
|
| +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
| if (s->next_proto_negotiated)
|
| OPENSSL_free(s->next_proto_negotiated);
|
| #endif
|
| @@ -850,7 +907,7 @@
|
| }
|
| 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)
|
| @@ -1006,6 +1063,11 @@
|
| s->max_cert_list=larg;
|
| return(l);
|
| case SSL_CTRL_SET_MTU:
|
| +#ifndef OPENSSL_NO_DTLS1
|
| + if (larg < (long)dtls1_min_mtu())
|
| + return 0;
|
| +#endif
|
| +
|
| if (SSL_version(s) == DTLS1_VERSION ||
|
| SSL_version(s) == DTLS1_BAD_VER)
|
| {
|
| @@ -1013,6 +1075,11 @@
|
| 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;
|
| @@ -1035,7 +1102,7 @@
|
| }
|
| }
|
|
|
| -struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx)
|
| +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
|
| {
|
| return ctx->sessions;
|
| }
|
| @@ -1078,7 +1145,7 @@
|
| 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:
|
| @@ -1109,6 +1176,11 @@
|
| 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));
|
| }
|
| @@ -1213,8 +1285,8 @@
|
| /* 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)
|
| @@ -1245,6 +1317,32 @@
|
| return 1;
|
| }
|
|
|
| +/** specify the ciphers to be used by the SSL */
|
| +int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk)
|
| + {
|
| + STACK_OF(SSL_CIPHER) *tmp_cipher_list;
|
| +
|
| + if (sk == NULL)
|
| + return 0;
|
| +
|
| + /* Based on end of ssl_create_cipher_list */
|
| + tmp_cipher_list = sk_SSL_CIPHER_dup(sk);
|
| + if (tmp_cipher_list == NULL)
|
| + {
|
| + return 0;
|
| + }
|
| + if (s->cipher_list != NULL)
|
| + sk_SSL_CIPHER_free(s->cipher_list);
|
| + s->cipher_list = sk;
|
| + if (s->cipher_list_by_id != NULL)
|
| + sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
| + s->cipher_list_by_id = tmp_cipher_list;
|
| + (void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp);
|
| +
|
| + sk_SSL_CIPHER_sort(s->cipher_list_by_id);
|
| + return 1;
|
| + }
|
| +
|
| /* works well for SSLv2, not so good for SSLv3 */
|
| char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
|
| {
|
| @@ -1282,13 +1380,13 @@
|
| }
|
|
|
| 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);
|
| @@ -1298,10 +1396,16 @@
|
| {
|
| c=sk_SSL_CIPHER_value(sk,i);
|
| #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;
|
| }
|
| @@ -1312,7 +1416,7 @@
|
| {
|
| 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;
|
| @@ -1327,7 +1431,7 @@
|
| 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)
|
| @@ -1390,6 +1494,7 @@
|
| 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).
|
| @@ -1411,9 +1516,127 @@
|
| 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)
|
| +static unsigned long ssl_session_hash(const SSL_SESSION *a)
|
| {
|
| unsigned long l;
|
|
|
| @@ -1430,7 +1653,7 @@
|
| * 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);
|
| @@ -1443,27 +1666,19 @@
|
| * 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);
|
| return(NULL);
|
| }
|
|
|
| -#ifdef OPENSSL_FIPS
|
| - if (FIPS_mode() && (meth->version < TLS1_VERSION))
|
| - {
|
| - SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
|
| - return NULL;
|
| - }
|
| -#endif
|
| -
|
| if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0)
|
| {
|
| SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
|
| @@ -1526,15 +1741,14 @@
|
| 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)
|
| {
|
| @@ -1570,6 +1784,8 @@
|
| 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;
|
| @@ -1582,10 +1798,34 @@
|
| 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_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
|
| @@ -1624,6 +1864,20 @@
|
| { 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;
|
| @@ -1661,7 +1915,7 @@
|
| 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);
|
| @@ -1681,11 +1935,23 @@
|
| #else
|
| a->comp_methods = NULL;
|
| #endif
|
| +
|
| +#ifndef OPENSSL_NO_PSK
|
| + if (a->psk_identity_hint)
|
| + OPENSSL_free(a->psk_identity_hint);
|
| +#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);
|
| }
|
|
|
| @@ -1716,20 +1982,20 @@
|
| 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;
|
|
|
| @@ -1769,60 +2035,77 @@
|
| 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
|
| @@ -1830,7 +2113,7 @@
|
| */
|
| 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) ?
|
| @@ -1838,35 +2121,46 @@
|
| 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
|
| }
|
| @@ -1874,12 +2168,22 @@
|
| #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;
|
| }
|
|
|
| @@ -1887,13 +2191,18 @@
|
| #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, const SSL_CIPHER *cs)
|
| {
|
| - 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;
|
|
|
| + alg_k = cs->algorithm_mkey;
|
| + alg_a = cs->algorithm_auth;
|
| +
|
| if (SSL_C_IS_EXPORT(cs))
|
| {
|
| /* ECDH key length in export ciphers must be <= 163 bits */
|
| @@ -1907,38 +2216,44 @@
|
| /* 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)
|
| {
|
| /* 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)
|
| {
|
| /* 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;
|
| }
|
| }
|
| @@ -1946,58 +2261,63 @@
|
| return 1; /* all checks are ok */
|
| }
|
|
|
| +#endif
|
| +
|
| /* THIS NEEDS CLEANING UP */
|
| X509 *ssl_get_server_send_cert(SSL *s)
|
| {
|
| - unsigned long alg,mask,kalg;
|
| + unsigned long alg_k,alg_a;
|
| CERT *c;
|
| - int i,is_export;
|
| + int i;
|
|
|
| c=s->cert;
|
| ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
|
| - alg=s->s3->tmp.new_cipher->algorithms;
|
| - is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
|
| - mask=is_export?c->export_mask:c->mask;
|
| - 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);
|
| @@ -2007,18 +2327,18 @@
|
| 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)
|
| {
|
| - unsigned long alg;
|
| + unsigned long alg_a;
|
| CERT *c;
|
|
|
| - 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)
|
| + else if (alg_a & SSL_aRSA)
|
| {
|
| if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
|
| return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
|
| @@ -2027,10 +2347,10 @@
|
| else
|
| return(NULL);
|
| }
|
| - 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) */
|
| + else /* if (alg_a & SSL_aNULL) */
|
| {
|
| SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
|
| return(NULL);
|
| @@ -2045,14 +2365,14 @@
|
| * 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);
|
| }
|
|
|
| @@ -2061,20 +2381,20 @@
|
| ((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;
|
| @@ -2119,9 +2439,6 @@
|
| return(SSL_ERROR_SSL);
|
| }
|
|
|
| - if ((i < 0) && SSL_want_server_random_validation(s))
|
| - return(SSL_ERROR_SERVER_RANDOM_VALIDATION_PENDING);
|
| -
|
| if ((i < 0) && SSL_want_read(s))
|
| {
|
| bio=SSL_get_rbio(s);
|
| @@ -2220,6 +2537,8 @@
|
| 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)
|
| @@ -2230,6 +2549,8 @@
|
| 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)
|
| @@ -2256,25 +2577,52 @@
|
| return(NULL);
|
| }
|
|
|
| -const char *SSL_get_version(const SSL *s)
|
| +static const char *ssl_get_version(int version)
|
| {
|
| - if (s->version == TLS1_VERSION)
|
| + if (version == TLS1_VERSION)
|
| return("TLSv1");
|
| - else if (s->version == SSL3_VERSION)
|
| + else if (version == SSL3_VERSION)
|
| return("SSLv3");
|
| - else if (s->version == SSL2_VERSION)
|
| + else if (version == SSL2_VERSION)
|
| return("SSLv2");
|
| else
|
| return("unknown");
|
| }
|
|
|
| +const char *SSL_get_version(const SSL *s)
|
| + {
|
| + return ssl_get_version(s->version);
|
| + }
|
| +
|
| +const char *SSL_SESSION_get_version(const SSL_SESSION *s)
|
| + {
|
| + return ssl_get_version(s->ssl_version);
|
| + }
|
| +
|
| +const char* SSL_authentication_method(const SSL* ssl)
|
| + {
|
| + if (ssl->cert != NULL && ssl->cert->rsa_tmp != NULL)
|
| + return SSL_TXT_RSA "_" SSL_TXT_EXPORT;
|
| + switch (ssl->version)
|
| + {
|
| + case SSL2_VERSION:
|
| + return SSL_TXT_RSA;
|
| + case SSL3_VERSION:
|
| + case TLS1_VERSION:
|
| + case DTLS1_VERSION:
|
| + return SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher);
|
| + default:
|
| + return "UNKNOWN";
|
| + }
|
| + }
|
| +
|
| SSL *SSL_dup(SSL *s)
|
| {
|
| STACK_OF(X509_NAME) *sk;
|
| X509_NAME *xn;
|
| SSL *ret;
|
| int i;
|
| -
|
| +
|
| if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL)
|
| return(NULL);
|
|
|
| @@ -2444,7 +2792,7 @@
|
| 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);
|
| @@ -2522,7 +2870,7 @@
|
| 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;
|
| @@ -2607,7 +2955,7 @@
|
|
|
| /* 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;
|
| }
|
| @@ -2728,13 +3076,13 @@
|
|
|
| #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);
|
| }
|
| @@ -2742,200 +3090,119 @@
|
|
|
| #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
|
|
|
| -
|
| -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))
|
| +#ifndef OPENSSL_NO_PSK
|
| +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
|
| {
|
| - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
|
| + 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;
|
| }
|
| -void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
|
| - {
|
| - SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
|
| - }
|
|
|
| -#ifndef OPENSSL_NO_TLSEXT
|
| -/* 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)
|
| +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
|
| {
|
| - unsigned int i, j;
|
| - const unsigned char *result;
|
| - int status = OPENSSL_NPN_UNSUPPORTED;
|
| + if (s == NULL)
|
| + return 0;
|
|
|
| - /* For each protocol in server preference order, see if we support it. */
|
| - for (i = 0; i < server_len; )
|
| + if (s->session == NULL)
|
| + return 1; /* session not created yet, ignored */
|
| +
|
| + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_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++;
|
| + 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;
|
| + }
|
|
|
| - /* 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;
|
| +const char *SSL_get_psk_identity_hint(const SSL *s)
|
| + {
|
| + if (s == NULL || s->session == NULL)
|
| + return NULL;
|
| + return(s->session->psk_identity_hint);
|
| }
|
|
|
| -/* 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)
|
| +const char *SSL_get_psk_identity(const SSL *s)
|
| {
|
| - *data = s->next_proto_negotiated;
|
| - if (!*data) {
|
| - *len = 0;
|
| - } else {
|
| - *len = s->next_proto_negotiated_len;
|
| + if (s == NULL || s->session == NULL)
|
| + return NULL;
|
| + return(s->session->psk_identity);
|
| }
|
| -}
|
|
|
| -/* 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)
|
| +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))
|
| {
|
| - ctx->next_protos_advertised_cb = cb;
|
| - ctx->next_protos_advertised_cb_arg = arg;
|
| + s->psk_client_callback = cb;
|
| }
|
|
|
| -/* 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)
|
| +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->next_proto_select_cb = cb;
|
| - ctx->next_proto_select_cb_arg = arg;
|
| + ctx->psk_client_callback = cb;
|
| }
|
|
|
| -/* SSL_CTX_set_snap_start_orbit sets the orbit value which will be echoed back
|
| - * to the client and enables Snap Start for this context.
|
| - *
|
| - * An orbit value can be used to spatially partition the state needed to support
|
| - * Snap Start. See the comments above SSL_set_suggested_server_random_validity
|
| - * (below). */
|
| -void SSL_CTX_set_snap_start_orbit(SSL_CTX *ctx, const unsigned char orbit[8])
|
| +void SSL_set_psk_server_callback(SSL *s,
|
| + unsigned int (*cb)(SSL *ssl, const char *identity,
|
| + unsigned char *psk, unsigned int max_psk_len))
|
| {
|
| - memcpy(ctx->snap_start_orbit, orbit, sizeof(ctx->snap_start_orbit));
|
| - ctx->snap_start_orbit_valid = 1;
|
| + s->psk_server_callback = cb;
|
| }
|
|
|
| -/* Once SSL_accept has returned with SSL_SERVER_RANDOM_VALIDATE, then one can
|
| - * call this function in order to get the client's suggested server random
|
| - * value. */
|
| -void SSL_get0_suggested_server_random(const SSL* s, const unsigned char **data, unsigned *length)
|
| +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))
|
| {
|
| - if (!s->s3->snap_start_requested)
|
| - {
|
| - *data = NULL;
|
| - *length = 0;
|
| - return;
|
| - }
|
| - *length = 32;
|
| - *data = s->s3->server_random;
|
| + ctx->psk_server_callback = cb;
|
| }
|
| +#endif
|
|
|
| -/* SSL_set_suggested_server_random_validity passes judgement on a
|
| - * client-suggested random value (obtained from
|
| - * SSL_get0_suggested_server_random). Rejecting the value triggers a recovery,
|
| - * while accepting the value /may/ result in a successful Snap Start, as long
|
| - * as the client predicted the handshake correctly.
|
| - *
|
| - * In order to accept a random value the user must ensure that it has NEVER
|
| - * been used before by this server, or any server configured with any of the
|
| - * same certificates. It may reject more if necessary.
|
| - *
|
| - * The first four bytes of the random value contain a timestamp (UNIX seconds
|
| - * since the epoch) which can be used to manage a time window. Additionally,
|
| - * the following eight bytes contain the orbit which which can also bound the
|
| - * state required if geographically separate servers share certificates.
|
| - *
|
| - * It's recommended that the time window have a maximum size, independent of
|
| - * the resources available, in order to prevent an attacker from arbitrarily
|
| - * delaying a Snap Start handshake.
|
| - */
|
| -void SSL_set_suggested_server_random_validity(SSL *s, char is_valid)
|
| +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))
|
| {
|
| - if (is_valid)
|
| - s->s3->server_random_suggestion_valid = 1;
|
| - else
|
| - ssl3_snap_start_reset_for_recovery(s);
|
| + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
|
| }
|
| +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
|
| + {
|
| + SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
|
| + }
|
|
|
| -#endif
|
| -
|
| int SSL_cutthrough_complete(const SSL *s)
|
| {
|
| return (!s->server && /* cutthrough only applies to clients */
|
| @@ -2949,9 +3216,32 @@
|
| s->state == SSL3_ST_CR_FINISHED_A));
|
| }
|
|
|
| +/* 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;
|
| +}
|
| +
|
| #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
|
| #include "../crypto/bio/bss_file.c"
|
| #endif
|
|
|
| IMPLEMENT_STACK_OF(SSL_CIPHER)
|
| IMPLEMENT_STACK_OF(SSL_COMP)
|
| +IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER,
|
| + ssl_cipher_id);
|
| +
|
|
|