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); |
+ |