X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=7fb4bdf1598b1b8159f432c7fcf6ce7bde391513;hp=7d40632ddf81e74ffafef63eac1f9d0f8fdea0d6;hb=0deea0e03cec1db2b6fe5a3328b5ce0f65b3e2bf;hpb=3ed449e94a55ee2b8a49d947bcfac582928cf34a diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 7d40632ddf..7fb4bdf159 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -58,7 +58,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -115,17 +115,51 @@ * 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 #endif #include +#include #include "ssl_locl.h" #include "kssl_lcl.h" #include #include #include +#include +#include +#ifndef OPENSSL_NO_DH #include +#endif +#ifndef OPENSSL_NO_ENGINE +#include +#endif const char *SSL_version_str=OPENSSL_VERSION_TEXT; @@ -136,7 +170,14 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={ ssl_undefined_function, (int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function, (int (*)(SSL*, int))ssl_undefined_function, - (int (*)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char*, int, unsigned char *))ssl_undefined_function + (int (*)(SSL *, const char*, int, unsigned char *))ssl_undefined_function, + 0, /* finish_mac_length */ + (int (*)(SSL *, int, unsigned char *))ssl_undefined_function, + NULL, /* client_finished_label */ + 0, /* client_finished_label_len */ + NULL, /* server_finished_label */ + 0, /* server_finished_label_len */ + (int (*)(int))ssl_undefined_function }; int SSL_clear(SSL *s) @@ -162,9 +203,9 @@ int SSL_clear(SSL *s) * needed because SSL_clear is not called when doing renegotiation) */ /* This is set if we are doing dynamic renegotiation so keep * the old cipher. It is sort of a SSL_clear_lite :-) */ - if (s->new_session) return(1); + if (s->renegotiate) return(1); #else - if (s->new_session) + if (s->renegotiate) { SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR); return 0; @@ -190,6 +231,8 @@ int SSL_clear(SSL *s) } ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); s->first_packet=0; @@ -210,14 +253,15 @@ int SSL_clear(SSL *s) } /** Used to change an SSL_CTXs default SSL method type */ -int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth) +int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth) { STACK_OF(SSL_CIPHER) *sk; ctx->method=meth; sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), - &(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST); + &(ctx->cipher_list_by_id), + meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); @@ -276,6 +320,7 @@ SSL *SSL_new(SSL_CTX *ctx) s->msg_callback=ctx->msg_callback; s->msg_callback_arg=ctx->msg_callback_arg; s->verify_mode=ctx->verify_mode; + s->not_resumable_session_cb=ctx->not_resumable_session_cb; #if 0 s->verify_depth=ctx->verify_depth; #endif @@ -294,9 +339,26 @@ SSL *SSL_new(SSL_CTX *ctx) s->trust = ctx->trust; #endif s->quiet_shutdown=ctx->quiet_shutdown; + s->max_send_fragment = ctx->max_send_fragment; CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); s->ctx=ctx; +#ifndef OPENSSL_NO_TLSEXT + s->tlsext_debug_cb = 0; + s->tlsext_debug_arg = NULL; + s->tlsext_ticket_expected = 0; + s->tlsext_status_type = -1; + s->tlsext_status_expected = 0; + s->tlsext_ocsp_ids = NULL; + s->tlsext_ocsp_exts = NULL; + s->tlsext_ocsp_resp = NULL; + 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; @@ -312,6 +374,11 @@ SSL *SSL_new(SSL_CTX *ctx) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); +#ifndef OPENSSL_NO_PSK + s->psk_client_callback=ctx->psk_client_callback; + s->psk_server_callback=ctx->psk_server_callback; +#endif + return(s); err: if (s != NULL) @@ -399,7 +466,7 @@ int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, } CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - p = (SSL_SESSION *)lh_retrieve(ssl->ctx->sessions, &r); + p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); return (p != NULL); } @@ -424,6 +491,16 @@ int SSL_set_trust(SSL *s, int trust) return X509_VERIFY_PARAM_set_trust(s->param, trust); } +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) + { + return X509_VERIFY_PARAM_set1(ctx->param, vpm); + } + +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) + { + return X509_VERIFY_PARAM_set1(ssl->param, vpm); + } + void SSL_free(SSL *s) { int i; @@ -478,22 +555,47 @@ void SSL_free(SSL *s) } ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); if (s->cert != NULL) ssl_cert_free(s->cert); /* Free up if allocated */ - if (s->ctx) SSL_CTX_free(s->ctx); +#ifndef OPENSSL_NO_TLSEXT + 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); + if (s->tlsext_ocsp_ids) + sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); + 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); if (s->method != NULL) s->method->ssl_free(s); + if (s->ctx) SSL_CTX_free(s->ctx); + #ifndef OPENSSL_NO_KRB5 if (s->kssl_ctx != NULL) kssl_ctx_free(s->kssl_ctx); #endif /* OPENSSL_NO_KRB5 */ +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + if (s->next_proto_negotiated) + OPENSSL_free(s->next_proto_negotiated); +#endif + OPENSSL_free(s); } @@ -806,7 +908,7 @@ int SSL_check_private_key(const SSL *ssl) } if (ssl->cert == NULL) { - SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); return 0; } if (ssl->cert->key->x509 == NULL) @@ -866,7 +968,7 @@ int SSL_peek(SSL *s,void *buf,int num) { if (s->handshake_func == 0) { - SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED); + SSLerr(SSL_F_SSL_PEEK, SSL_R_UNINITIALIZED); return -1; } @@ -916,18 +1018,29 @@ int SSL_shutdown(SSL *s) int SSL_renegotiate(SSL *s) { - if (s->new_session == 0) - { - s->new_session=1; - } + if (s->renegotiate == 0) + s->renegotiate=1; + + s->new_session=1; + return(s->method->ssl_renegotiate(s)); } +int SSL_renegotiate_abbreviated(SSL *s) +{ + if (s->renegotiate == 0) + s->renegotiate=1; + + s->new_session=0; + + return(s->method->ssl_renegotiate(s)); +} + int SSL_renegotiate_pending(SSL *s) { /* becomes true when negotiation is requested; * false again once a handshake has finished */ - return (s->new_session != 0); + return (s->renegotiate != 0); } long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) @@ -949,14 +1062,35 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) case SSL_CTRL_OPTIONS: return(s->options|=larg); + case SSL_CTRL_CLEAR_OPTIONS: + return(s->options&=~larg); case SSL_CTRL_MODE: return(s->mode|=larg); + case SSL_CTRL_CLEAR_MODE: + return(s->mode &=~larg); case SSL_CTRL_GET_MAX_CERT_LIST: return(s->max_cert_list); case SSL_CTRL_SET_MAX_CERT_LIST: l=s->max_cert_list; s->max_cert_list=larg; return(l); + case SSL_CTRL_SET_MTU: + if (SSL_version(s) == DTLS1_VERSION || + SSL_version(s) == DTLS1_BAD_VER) + { + s->d1->mtu = larg; + 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; + else return 0; default: return(s->method->ssl_ctrl(s,cmd,larg,parg)); } @@ -975,7 +1109,7 @@ long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) } } -struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx) +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; } @@ -1018,7 +1152,7 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) return(ctx->session_cache_mode); case SSL_CTRL_SESS_NUMBER: - return(ctx->sessions->num_items); + return(lh_SSL_SESSION_num_items(ctx->sessions)); case SSL_CTRL_SESS_CONNECT: return(ctx->stats.sess_connect); case SSL_CTRL_SESS_CONNECT_GOOD: @@ -1043,8 +1177,17 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) return(ctx->stats.sess_cache_full); case SSL_CTRL_OPTIONS: return(ctx->options|=larg); + case SSL_CTRL_CLEAR_OPTIONS: + return(ctx->options&=~larg); case SSL_CTRL_MODE: 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)); } @@ -1146,8 +1289,21 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, &ctx->cipher_list_by_id,str); -/* XXXX */ - return((sk == NULL)?0:1); + /* 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 + * ctx->cipher_list and ctx->cipher_list_by_id has been + * updated. */ + if (sk == NULL) + return 0; + else if (sk_SSL_CIPHER_num(sk) == 0) + { + SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); + return 0; + } + return 1; } /** specify the ciphers to be used by the SSL */ @@ -1157,15 +1313,21 @@ int SSL_set_cipher_list(SSL *s,const char *str) sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, &s->cipher_list_by_id,str); -/* XXXX */ - return((sk == NULL)?0:1); + /* see comment in SSL_CTX_set_cipher_list */ + if (sk == NULL) + return 0; + else if (sk_SSL_CIPHER_num(sk) == 0) + { + SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH); + return 0; + } + return 1; } /* works well for SSLv2, not so good for SSLv3 */ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) { char *p; - const char *cp; STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *c; int i; @@ -1178,32 +1340,34 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) sk=s->session->ciphers; for (i=0; iname; *cp; ) + n=strlen(c->name); + if (n+1 > len) { - if (len-- == 0) - { - *p='\0'; - return(buf); - } - else - *(p++)= *(cp++); + if (p != buf) + --p; + *p='\0'; + return buf; } + strcpy(p,c->name); + p+=n; *(p++)=':'; + len-=n+1; } p[-1]='\0'; return(buf); } -int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p) +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 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); @@ -1213,21 +1377,46 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p) { c=sk_SSL_CIPHER_value(sk,i); #ifndef OPENSSL_NO_KRB5 - if ((c->algorithms & SSL_KRB5) && nokrb5) - continue; -#endif /* OPENSSL_NO_KRB5 */ - j=ssl_put_cipher_by_char(s,c,p); + if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) && + nokrb5) + continue; +#endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_PSK + /* with PSK there must be client callback set */ + if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) && + s->psk_client_callback == NULL) + continue; +#endif /* OPENSSL_NO_PSK */ + j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p); p+=j; } + /* If p == q, no ciphers and caller indicates an error. Otherwise + * add SCSV if not renegotiating. + */ + if (p != q && !s->renegotiate) + { + static SSL_CIPHER scsv = + { + 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; +#ifdef OPENSSL_RI_DEBUG + fprintf(stderr, "SCSV sent by client\n"); +#endif + } + return(p-q); } 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) + s->s3->send_connection_binding = 0; n=ssl_put_cipher_by_char(s,NULL,NULL); if ((num%n) != 0) @@ -1245,6 +1434,26 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, for (i=0; is3 && (n != 3 || !p[0]) && + (p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) && + (p[n-1] == (SSL3_CK_SCSV & 0xff))) + { + /* SCSV fatal if renegotiating */ + if (s->renegotiate) + { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + s->s3->send_connection_binding = 1; + p += n; +#ifdef OPENSSL_RI_DEBUG + fprintf(stderr, "SCSV received by server\n"); +#endif + continue; + } + c=ssl_get_cipher_by_char(s,p); p+=n; if (c != NULL) @@ -1266,7 +1475,149 @@ err: return(NULL); } -unsigned long SSL_SESSION_hash(const SSL_SESSION *a) + +#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). + */ + +const char *SSL_get_servername(const SSL *s, const int type) + { + if (type != TLSEXT_NAMETYPE_host_name) + return NULL; + + return s->session && !s->tlsext_hostname ? + s->session->tlsext_hostname : + s->tlsext_hostname; + } + +int SSL_get_servername_type(const SSL *s) + { + if (s->session && (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname)) + 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 + +static unsigned long ssl_session_hash(const SSL_SESSION *a) { unsigned long l; @@ -1283,7 +1634,7 @@ unsigned long SSL_SESSION_hash(const SSL_SESSION *a) * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being * able to construct an SSL_SESSION that will collide with any existing session * with a matching session ID. */ -int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b) +static int ssl_session_cmp(const SSL_SESSION *a,const SSL_SESSION *b) { if (a->ssl_version != b->ssl_version) return(1); @@ -1296,13 +1647,13 @@ int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b) * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each * variable. The reason is that the functions aren't static, they're exposed via * ssl.h. */ -static IMPLEMENT_LHASH_HASH_FN(SSL_SESSION_hash, SSL_SESSION *) -static IMPLEMENT_LHASH_COMP_FN(SSL_SESSION_cmp, SSL_SESSION *) +static IMPLEMENT_LHASH_HASH_FN(ssl_session, SSL_SESSION) +static IMPLEMENT_LHASH_COMP_FN(ssl_session, SSL_SESSION) -SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { SSL_CTX *ret=NULL; - + if (meth == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED); @@ -1368,16 +1719,17 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) ret->default_passwd_callback=0; ret->default_passwd_callback_userdata=NULL; ret->client_cert_cb=0; + 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) { @@ -1413,6 +1765,76 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) ret->extra_certs=NULL; ret->comp_methods=SSL_COMP_get_compression_methods(); + ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + +#ifndef OPENSSL_NO_TLSEXT + ret->tlsext_servername_callback = 0; + ret->tlsext_servername_arg = NULL; + /* Setup RFC4507 ticket keys */ + if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16) <= 0) + || (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <= 0) + || (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0)) + ret->options |= SSL_OP_NO_TICKET; + + ret->tlsext_status_cb = 0; + ret->tlsext_status_arg = NULL; + +# ifndef OPENSSL_NO_NEXTPROTONEG + ret->next_protos_advertised_cb = 0; + ret->next_proto_select_cb = 0; +# endif +#endif +#ifndef OPENSSL_NO_PSK + ret->psk_identity_hint=NULL; + ret->psk_client_callback=NULL; + ret->psk_server_callback=NULL; +#endif +#ifndef OPENSSL_NO_SRP + SSL_CTX_SRP_CTX_init(ret); +#endif +#ifndef OPENSSL_NO_BUF_FREELISTS + ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; + ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); + if (!ret->rbuf_freelist) + goto err; + ret->rbuf_freelist->chunklen = 0; + ret->rbuf_freelist->len = 0; + ret->rbuf_freelist->head = NULL; + ret->wbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); + if (!ret->wbuf_freelist) + { + OPENSSL_free(ret->rbuf_freelist); + goto err; + } + ret->wbuf_freelist->chunklen = 0; + ret->wbuf_freelist->len = 0; + ret->wbuf_freelist->head = NULL; +#endif +#ifndef OPENSSL_NO_ENGINE + ret->client_cert_engine = NULL; +#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO +#define eng_strx(x) #x +#define eng_str(x) eng_strx(x) + /* Use specific client engine automatically... ignore errors */ + { + ENGINE *eng; + eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + if (!eng) + { + ERR_clear_error(); + ENGINE_load_builtin_engines(); + eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + } + if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng)) + ERR_clear_error(); + } +#endif +#endif + /* Default is to connect to non-RI servers. When RI is more widely + * deployed might change this. + */ + ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + return(ret); err: SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE); @@ -1426,6 +1848,20 @@ static void SSL_COMP_free(SSL_COMP *comp) { OPENSSL_free(comp); } #endif +#ifndef OPENSSL_NO_BUF_FREELISTS +static void +ssl_buf_freelist_free(SSL3_BUF_FREELIST *list) + { + SSL3_BUF_FREELIST_ENTRY *ent, *next; + for (ent = list->head; ent; ent = next) + { + next = ent->next; + OPENSSL_free(ent); + } + OPENSSL_free(list); + } +#endif + void SSL_CTX_free(SSL_CTX *a) { int i; @@ -1463,7 +1899,7 @@ void SSL_CTX_free(SSL_CTX *a) CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); if (a->sessions != NULL) - lh_free(a->sessions); + lh_SSL_SESSION_free(a->sessions); if (a->cert_store != NULL) X509_STORE_free(a->cert_store); @@ -1483,6 +1919,26 @@ void SSL_CTX_free(SSL_CTX *a) #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_SRP + SSL_CTX_SRP_CTX_free(a); +#endif +#ifndef OPENSSL_NO_ENGINE + if (a->client_cert_engine) + ENGINE_finish(a->client_cert_engine); +#endif + +#ifndef OPENSSL_NO_BUF_FREELISTS + if (a->wbuf_freelist) + ssl_buf_freelist_free(a->wbuf_freelist); + if (a->rbuf_freelist) + ssl_buf_freelist_free(a->rbuf_freelist); +#endif + OPENSSL_free(a); } @@ -1513,14 +1969,17 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) X509_VERIFY_PARAM_set_depth(ctx->param, depth); } -void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) +void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) { CERT_PKEY *cpk; int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign; int rsa_enc_export,dh_rsa_export,dh_dsa_export; int rsa_tmp_export,dh_tmp_export,kl; - unsigned long mask,emask; - int have_ecc_cert, have_ecdh_tmp, ecdh_ok, ecdsa_ok, ecc_pkey_size; + 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; @@ -1563,60 +2022,77 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_ECC]); have_ecc_cert= (cpk->x509 != NULL && cpk->privatekey != NULL); - mask=0; - emask=0; + mask_k=0; + mask_a=0; + emask_k=0; + emask_a=0; + + #ifdef CIPHER_DEBUG - printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", - rsa_tmp,rsa_tmp_export,dh_tmp, + printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", + rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp, rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa); #endif + + cpk = &(c->pkeys[SSL_PKEY_GOST01]); + if (cpk->x509 != NULL && cpk->privatekey !=NULL) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST01; + } + cpk = &(c->pkeys[SSL_PKEY_GOST94]); + if (cpk->x509 != NULL && cpk->privatekey !=NULL) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST94; + } if (rsa_enc || (rsa_tmp && rsa_sign)) - mask|=SSL_kRSA; + mask_k|=SSL_kRSA; if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc))) - emask|=SSL_kRSA; + emask_k|=SSL_kRSA; #if 0 /* The match needs to be both kEDH and aRSA or aDSA, so don't worry */ - if ( (dh_tmp || dh_rsa || dh_dsa) && + if ( (dh_tmp || dh_rsa || dh_dsa) && (rsa_enc || rsa_sign || dsa_sign)) - mask|=SSL_kEDH; + mask_k|=SSL_kEDH; if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && (rsa_enc || rsa_sign || dsa_sign)) - emask|=SSL_kEDH; + emask_k|=SSL_kEDH; #endif - if (dh_tmp_export) - emask|=SSL_kEDH; + if (dh_tmp_export) + emask_k|=SSL_kEDH; if (dh_tmp) - mask|=SSL_kEDH; + mask_k|=SSL_kEDH; - if (dh_rsa) mask|=SSL_kDHr; - if (dh_rsa_export) emask|=SSL_kDHr; + if (dh_rsa) mask_k|=SSL_kDHr; + if (dh_rsa_export) emask_k|=SSL_kDHr; - if (dh_dsa) mask|=SSL_kDHd; - if (dh_dsa_export) emask|=SSL_kDHd; + if (dh_dsa) mask_k|=SSL_kDHd; + if (dh_dsa_export) emask_k|=SSL_kDHd; if (rsa_enc || rsa_sign) { - mask|=SSL_aRSA; - emask|=SSL_aRSA; + mask_a|=SSL_aRSA; + emask_a|=SSL_aRSA; } if (dsa_sign) { - mask|=SSL_aDSS; - emask|=SSL_aDSS; + mask_a|=SSL_aDSS; + emask_a|=SSL_aDSS; } - mask|=SSL_aNULL; - emask|=SSL_aNULL; + mask_a|=SSL_aNULL; + emask_a|=SSL_aNULL; #ifndef OPENSSL_NO_KRB5 - mask|=SSL_kKRB5|SSL_aKRB5; - emask|=SSL_kKRB5|SSL_aKRB5; + mask_k|=SSL_kKRB5; + mask_a|=SSL_aKRB5; + emask_k|=SSL_kKRB5; + emask_a|=SSL_aKRB5; #endif /* An ECC certificate may be usable for ECDH and/or @@ -1624,7 +2100,7 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) */ if (have_ecc_cert) { - /* This call populates extension flags (ex_flags) */ + /* This call populates extension flags (ex_flags) */ x = (c->pkeys[SSL_PKEY_ECC]).x509; X509_check_purpose(x, -1, 0); ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? @@ -1632,7 +2108,7 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; ecc_pkey = X509_get_pubkey(x); - ecc_pkey_size = (ecc_pkey != NULL) ? + ecc_pkey_size = (ecc_pkey != NULL) ? EVP_PKEY_bits(ecc_pkey) : 0; EVP_PKEY_free(ecc_pkey); if ((x->sig_alg) && (x->sig_alg->algorithm)) @@ -1640,27 +2116,41 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) #ifndef OPENSSL_NO_ECDH if (ecdh_ok) { - if ((signature_nid == NID_md5WithRSAEncryption) || - (signature_nid == NID_md4WithRSAEncryption) || - (signature_nid == NID_md2WithRSAEncryption)) + const char *sig = OBJ_nid2ln(signature_nid); + if (sig == NULL) { - mask|=SSL_kECDH|SSL_aRSA; + ERR_clear_error(); + sig = "unknown"; + } + + if (strstr(sig, "WithRSA")) + { + 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) { - 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 } @@ -1668,12 +2158,22 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) #ifndef OPENSSL_NO_ECDH if (have_ecdh_tmp) { - mask|=SSL_kECDHE; - emask|=SSL_kECDHE; + mask_k|=SSL_kEECDH; + emask_k|=SSL_kEECDH; } #endif - c->mask=mask; - c->export_mask=emask; + +#ifndef OPENSSL_NO_PSK + mask_k |= SSL_kPSK; + mask_a |= SSL_aPSK; + emask_k |= SSL_kPSK; + emask_a |= SSL_aPSK; +#endif + + c->mask_k=mask_k; + c->mask_a=mask_a; + c->export_mask_k=emask_k; + c->export_mask_a=emask_a; c->valid=1; } @@ -1681,13 +2181,18 @@ void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) #define ku_reject(x, usage) \ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) -int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs) +#ifndef OPENSSL_NO_EC + +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, 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; + 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 */ @@ -1702,37 +2207,46 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs) 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) + 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) { + 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)) + + const char *sig = OBJ_nid2ln(signature_nid); + if (sig == NULL) + { + ERR_clear_error(); + sig = "unknown"; + } + if (strstr(sig, "WithRSA") == NULL) { + 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; } } @@ -1740,58 +2254,63 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs) return 1; /* all checks are ok */ } +#endif + /* THIS NEEDS CLEANING UP */ X509 *ssl_get_server_send_cert(SSL *s) { - unsigned long alg,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); @@ -1801,18 +2320,18 @@ X509 *ssl_get_server_send_cert(SSL *s) return(c->pkeys[i].x509); } -EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher) +EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher) { - 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); @@ -1821,10 +2340,10 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher) 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); @@ -1839,14 +2358,14 @@ void ssl_update_cache(SSL *s,int mode) * and it would be rather hard to do anyway :-) */ if (s->session->session_id_length == 0) return; - i=s->ctx->session_cache_mode; + i=s->session_ctx->session_cache_mode; if ((i & mode) && (!s->hit) && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) - || SSL_CTX_add_session(s->ctx,s->session)) - && (s->ctx->new_session_cb != NULL)) + || SSL_CTX_add_session(s->session_ctx,s->session)) + && (s->session_ctx->new_session_cb != NULL)) { CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); - if (!s->ctx->new_session_cb(s,s->session)) + if (!s->session_ctx->new_session_cb(s,s->session)) SSL_SESSION_free(s->session); } @@ -1855,20 +2374,20 @@ void ssl_update_cache(SSL *s,int mode) ((i & mode) == mode)) { if ( (((mode & SSL_SESS_CACHE_CLIENT) - ?s->ctx->stats.sess_connect_good - :s->ctx->stats.sess_accept_good) & 0xff) == 0xff) + ?s->session_ctx->stats.sess_connect_good + :s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff) { - SSL_CTX_flush_sessions(s->ctx,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; @@ -2011,6 +2530,8 @@ void SSL_set_accept_state(SSL *s) s->handshake_func=s->method->ssl_accept; /* clear the current cipher */ ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); } void SSL_set_connect_state(SSL *s) @@ -2021,6 +2542,8 @@ void SSL_set_connect_state(SSL *s) s->handshake_func=s->method->ssl_connect; /* clear the current cipher */ ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); } int ssl_undefined_function(SSL *s) @@ -2049,7 +2572,9 @@ SSL_METHOD *ssl_bad_method(int ver) const char *SSL_get_version(const SSL *s) { - if (s->version == TLS1_VERSION) + if (s->version == TLS1_1_VERSION) + return("TLSv1.1"); + else if (s->version == TLS1_VERSION) return("TLSv1"); else if (s->version == SSL3_VERSION) return("SSLv3"); @@ -2065,7 +2590,7 @@ SSL *SSL_dup(SSL *s) X509_NAME *xn; SSL *ret; int i; - + if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) return(NULL); @@ -2143,6 +2668,7 @@ SSL *SSL_dup(SSL *s) ret->in_handshake = s->in_handshake; ret->handshake_func = s->handshake_func; ret->server = s->server; + ret->renegotiate = s->renegotiate; ret->new_session = s->new_session; ret->quiet_shutdown = s->quiet_shutdown; ret->shutdown=s->shutdown; @@ -2203,6 +2729,7 @@ void ssl_clear_cipher_ctx(SSL *s) OPENSSL_free(s->enc_write_ctx); s->enc_write_ctx=NULL; } +#ifndef OPENSSL_NO_COMP if (s->expand != NULL) { COMP_CTX_free(s->expand); @@ -2213,6 +2740,7 @@ void ssl_clear_cipher_ctx(SSL *s) COMP_CTX_free(s->compress); s->compress=NULL; } +#endif } /* Fix this function so that it takes an optional type parameter */ @@ -2233,12 +2761,22 @@ EVP_PKEY *SSL_get_privatekey(SSL *s) return(NULL); } -SSL_CIPHER *SSL_get_current_cipher(const SSL *s) +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) { if ((s->session != NULL) && (s->session->cipher != NULL)) return(s->session->cipher); return(NULL); } +#ifdef OPENSSL_NO_COMP +const void *SSL_get_current_compression(SSL *s) + { + return NULL; + } +const void *SSL_get_current_expansion(SSL *s) + { + return NULL; + } +#else const COMP_METHOD *SSL_get_current_compression(SSL *s) { @@ -2253,6 +2791,7 @@ const COMP_METHOD *SSL_get_current_expansion(SSL *s) return(s->expand->meth); return(NULL); } +#endif int ssl_init_wbio_buffer(SSL *s,int push) { @@ -2300,7 +2839,7 @@ void ssl_free_wbio_buffer(SSL *s) s->wbio=BIO_pop(s->wbio); #ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */ assert(s->wbio != NULL); -#endif +#endif } BIO_free(s->bbio); s->bbio=NULL; @@ -2346,6 +2885,24 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) return(ssl->ctx); } +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) + { + if (ssl->ctx == ctx) + return ssl->ctx; +#ifndef OPENSSL_NO_TLSEXT + if (ctx == NULL) + ctx = ssl->initial_ctx; +#endif + if (ssl->cert != NULL) + ssl_cert_free(ssl->cert); + ssl->cert = ssl_cert_dup(ctx->cert); + CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); + if (ssl->ctx != NULL) + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + ssl->ctx = ctx; + return(ssl->ctx); + } + #ifndef OPENSSL_NO_STDIO int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { @@ -2360,12 +2917,14 @@ int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, #endif void SSL_set_info_callback(SSL *ssl, - void (*cb)(const SSL *ssl,int type,int val)) + void (*cb)(const SSL *ssl,int type,int val)) { ssl->info_callback=cb; } -void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val) +/* 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*/) { return ssl->info_callback; } @@ -2486,13 +3045,13 @@ RSA *cb(SSL *ssl,int is_export,int keylength) #ifndef OPENSSL_NO_DH void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export, - int keylength)) + int keylength)) { SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); } void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export, - int keylength)) + int keylength)) { SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); } @@ -2500,18 +3059,109 @@ void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export, #ifndef OPENSSL_NO_ECDH void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export, - int keylength)) + int keylength)) { SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); } void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export, - int keylength)) + int keylength)) { SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); } #endif +#ifndef OPENSSL_NO_PSK +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) + { + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + if (ctx->psk_identity_hint != NULL) + OPENSSL_free(ctx->psk_identity_hint); + if (identity_hint != NULL) + { + ctx->psk_identity_hint = BUF_strdup(identity_hint); + if (ctx->psk_identity_hint == NULL) + return 0; + } + else + ctx->psk_identity_hint = NULL; + return 1; + } + +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) + { + if (s == NULL) + return 0; + + if (s->session == NULL) + return 1; /* session not created yet, ignored */ + + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + if (s->session->psk_identity_hint != NULL) + OPENSSL_free(s->session->psk_identity_hint); + if (identity_hint != NULL) + { + s->session->psk_identity_hint = BUF_strdup(identity_hint); + if (s->session->psk_identity_hint == NULL) + return 0; + } + else + s->session->psk_identity_hint = NULL; + return 1; + } + +const char *SSL_get_psk_identity_hint(const SSL *s) + { + if (s == NULL || s->session == NULL) + return NULL; + return(s->session->psk_identity_hint); + } + +const char *SSL_get_psk_identity(const SSL *s) + { + if (s == NULL || s->session == NULL) + return NULL; + return(s->session->psk_identity); + } + +void SSL_set_psk_client_callback(SSL *s, + unsigned int (*cb)(SSL *ssl, const char *hint, + char *identity, unsigned int max_identity_len, unsigned char *psk, + unsigned int max_psk_len)) + { + s->psk_client_callback = cb; + } + +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, + unsigned int (*cb)(SSL *ssl, const char *hint, + char *identity, unsigned int max_identity_len, unsigned char *psk, + unsigned int max_psk_len)) + { + ctx->psk_client_callback = cb; + } + +void SSL_set_psk_server_callback(SSL *s, + unsigned int (*cb)(SSL *ssl, const char *identity, + unsigned char *psk, unsigned int max_psk_len)) + { + s->psk_server_callback = cb; + } + +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, + unsigned int (*cb)(SSL *ssl, const char *identity, + unsigned char *psk, unsigned int max_psk_len)) + { + ctx->psk_server_callback = cb; + } +#endif void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) { @@ -2522,7 +3172,38 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); } +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb)(SSL *ssl, int is_forward_secure)) + { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); + } +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb)(SSL *ssl, int is_forward_secure)) + { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); + } +/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer + * vairable, freeing EVP_MD_CTX previously stored in that variable, if + * any. If EVP_MD pointer is passed, initializes ctx with this md + * Returns newly allocated ctx; + */ + +EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) +{ + ssl_clear_hash_ctx(hash); + *hash = EVP_MD_CTX_create(); + if (md) EVP_DigestInit_ex(*hash,md,NULL); + return *hash; +} +void ssl_clear_hash_ctx(EVP_MD_CTX **hash) +{ + + if (*hash) EVP_MD_CTX_destroy(*hash); + *hash=NULL; +} #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) #include "../crypto/bio/bss_file.c" @@ -2530,3 +3211,6 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con IMPLEMENT_STACK_OF(SSL_CIPHER) IMPLEMENT_STACK_OF(SSL_COMP) +IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, + ssl_cipher_id); +