X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=f9f91e666c09acc30c69ee774b252a9eda07ad59;hp=39bd9d7cf04bcaf304729df1812db1013f18b395;hb=ac8e9cbe14b59dacfe4ac52bc5ff06f8003e9b01;hpb=5430200b8b9528861ec9759623107f407ba8c38f diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 39bd9d7cf0..f9f91e666c 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -176,7 +176,10 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={ 0, /* client_finished_label_len */ NULL, /* server_finished_label */ 0, /* server_finished_label_len */ - (int (*)(int))ssl_undefined_function + (int (*)(int))ssl_undefined_function, + (int (*)(SSL *, unsigned char *, size_t, const char *, + size_t, const unsigned char *, size_t, + int use_context)) ssl_undefined_function, }; int SSL_clear(SSL *s) @@ -202,9 +205,9 @@ int SSL_clear(SSL *s) * needed because SSL_clear is not called when doing renegotiation) */ /* This is set if we are doing dynamic renegotiation so keep * the old cipher. It is sort of a SSL_clear_lite :-) */ - if (s->new_session) return(1); + if (s->renegotiate) return(1); #else - if (s->new_session) + if (s->renegotiate) { SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR); return 0; @@ -260,7 +263,7 @@ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,const SSL_METHOD *meth) sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), &(ctx->cipher_list_by_id), - meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); + SSL_DEFAULT_CIPHER_LIST, ctx->cert); if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); @@ -319,6 +322,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 @@ -353,6 +357,42 @@ SSL *SSL_new(SSL_CTX *ctx) s->tlsext_ocsp_resplen = -1; CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); s->initial_ctx=ctx; +#ifndef OPENSSL_NO_EC + if (ctx->tlsext_ecpointformatlist) + { + s->tlsext_ecpointformatlist = + BUF_memdup(ctx->tlsext_ecpointformatlist, + ctx->tlsext_ecpointformatlist_length); + if (!s->tlsext_ecpointformatlist) + goto err; + s->tlsext_ecpointformatlist_length = + ctx->tlsext_ecpointformatlist_length; + } + if (ctx->tlsext_ellipticcurvelist) + { + s->tlsext_ellipticcurvelist = + BUF_memdup(ctx->tlsext_ellipticcurvelist, + ctx->tlsext_ellipticcurvelist_length); + if (!s->tlsext_ellipticcurvelist) + goto err; + s->tlsext_ellipticcurvelist_length = + ctx->tlsext_ellipticcurvelist_length; + } +#endif +# ifndef OPENSSL_NO_NEXTPROTONEG + s->next_proto_negotiated = NULL; +# endif + + if (s->ctx->alpn_client_proto_list) + { + s->alpn_client_proto_list = + OPENSSL_malloc(s->ctx->alpn_client_proto_list_len); + if (s->alpn_client_proto_list == NULL) + goto err; + memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list, + s->ctx->alpn_client_proto_list_len); + s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; + } #endif s->verify_result=X509_V_OK; @@ -377,13 +417,7 @@ SSL *SSL_new(SSL_CTX *ctx) return(s); err: if (s != NULL) - { - if (s->cert != NULL) - ssl_cert_free(s->cert); - if (s->ctx != NULL) - SSL_CTX_free(s->ctx); /* decrement reference count */ - OPENSSL_free(s); - } + SSL_free(s); SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } @@ -448,17 +482,6 @@ int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, r.ssl_version = ssl->version; r.session_id_length = id_len; memcpy(r.session_id, id, id_len); - /* NB: SSLv2 always uses a fixed 16-byte session ID, so even if a - * callback is calling us to check the uniqueness of a shorter ID, it - * must be compared as a padded-out ID because that is what it will be - * converted to when the callback has finished choosing it. */ - if((r.ssl_version == SSL2_VERSION) && - (id_len < SSL2_SSL_SESSION_ID_LENGTH)) - { - memset(r.session_id + id_len, 0, - SSL2_SSL_SESSION_ID_LENGTH - id_len); - r.session_id_length = SSL2_SSL_SESSION_ID_LENGTH; - } CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); @@ -496,6 +519,21 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) return X509_VERIFY_PARAM_set1(ssl->param, vpm); } +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) + { + return ctx->param; + } + +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) + { + return ssl->param; + } + +void SSL_certs_clear(SSL *s) + { + ssl_cert_clear_certs(s->cert); + } + void SSL_free(SSL *s) { int i; @@ -572,6 +610,8 @@ void SSL_free(SSL *s) sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); if (s->tlsext_ocsp_resp) OPENSSL_free(s->tlsext_ocsp_resp); + if (s->alpn_client_proto_list) + OPENSSL_free(s->alpn_client_proto_list); #endif if (s->client_CA != NULL) @@ -586,6 +626,16 @@ void SSL_free(SSL *s) kssl_ctx_free(s->kssl_ctx); #endif /* OPENSSL_NO_KRB5 */ +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + if (s->next_proto_negotiated) + OPENSSL_free(s->next_proto_negotiated); +#endif + +#ifndef OPENSSL_NO_SRTP + if (s->srtp_profiles) + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); +#endif + OPENSSL_free(s); } @@ -1008,10 +1058,21 @@ int SSL_shutdown(SSL *s) int SSL_renegotiate(SSL *s) { - if (s->new_session == 0) - { - s->new_session=1; - } + if (s->renegotiate == 0) + s->renegotiate=1; + + s->new_session=1; + + return(s->method->ssl_renegotiate(s)); + } + +int SSL_renegotiate_abbreviated(SSL *s) + { + if (s->renegotiate == 0) + s->renegotiate=1; + + s->new_session=0; + return(s->method->ssl_renegotiate(s)); } @@ -1019,7 +1080,7 @@ int SSL_renegotiate_pending(SSL *s) { /* becomes true when negotiation is requested; * false again once a handshake has finished */ - return (s->new_session != 0); + return (s->renegotiate != 0); } long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) @@ -1041,22 +1102,18 @@ 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; @@ -1066,6 +1123,21 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) if (s->s3) return s->s3->send_connection_binding; else return 0; + case SSL_CTRL_CERT_FLAGS: + return(s->cert->cert_flags|=larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return(s->cert->cert_flags &=~larg); + + case SSL_CTRL_GET_RAW_CIPHERLIST: + if (parg) + { + if (s->cert->ciphers_raw == NULL) + return 0; + *(unsigned char **)parg = s->cert->ciphers_raw; + return (int)s->cert->ciphers_rawlen; + } + else + return ssl_put_cipher_by_char(s,NULL,NULL); default: return(s->method->ssl_ctrl(s,cmd,larg,parg)); } @@ -1092,6 +1164,22 @@ LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) { long l; + /* For some cases with ctx == NULL perform syntax checks */ + if (ctx == NULL) + { + switch (cmd) + { +#ifndef OPENSSL_NO_EC + case SSL_CTRL_SET_CURVES_LIST: + return tls1_set_curves_list(NULL, NULL, parg); +#endif + case SSL_CTRL_SET_SIGALGS_LIST: + case SSL_CTRL_SET_CLIENT_SIGALGS_LIST: + return tls1_set_sigalgs_list(NULL, parg, 0); + default: + return 0; + } + } switch (cmd) { @@ -1152,13 +1240,21 @@ 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; + case SSL_CTRL_CERT_FLAGS: + return(ctx->cert->cert_flags|=larg); + case SSL_CTRL_CLEAR_CERT_FLAGS: + return(ctx->cert->cert_flags &=~larg); default: return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); } @@ -1219,6 +1315,33 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) return(NULL); } +STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s) + { + STACK_OF(SSL_CIPHER) *sk = NULL, *ciphers; + int i; + ciphers = SSL_get_ciphers(s); + if (!ciphers) + return NULL; + ssl_set_client_disabled(s); + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) + { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); + if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + { + if (!sk) + sk = sk_SSL_CIPHER_new_null(); + if (!sk) + return NULL; + if (!sk_SSL_CIPHER_push(sk, c)) + { + sk_SSL_CIPHER_free(sk); + return NULL; + } + } + } + return sk; + } + /** return a STACK of the ciphers available for the SSL and in order of * algorithm id */ STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) @@ -1259,7 +1382,7 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, - &ctx->cipher_list_by_id,str); + &ctx->cipher_list_by_id,str, ctx->cert); /* 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 @@ -1283,7 +1406,7 @@ int SSL_set_cipher_list(SSL *s,const char *str) STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, - &s->cipher_list_by_id,str); + &s->cipher_list_by_id,str, s->cert); /* see comment in SSL_CTX_set_cipher_list */ if (sk == NULL) return 0; @@ -1309,6 +1432,10 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len) p=buf; sk=s->session->ciphers; + + if (sk_SSL_CIPHER_num(sk) == 0) + return NULL; + for (i=0; ikssl_ctx); -#endif /* OPENSSL_NO_KRB5 */ + int empty_reneg_info_scsv = !s->renegotiate; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); if (sk == NULL) return(0); q=p; + if (put_cb == NULL) + put_cb = s->method->put_cipher_by_char; for (i=0; ialgorithm_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) + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) continue; -#endif /* OPENSSL_NO_PSK */ - j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p); +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (c->id == SSL3_CK_SCSV) + { + if (!empty_reneg_info_scsv) + continue; + else + empty_reneg_info_scsv = 0; + } +#endif + j = put_cb(c,p); p+=j; } - /* If p == q, no ciphers and caller indicates an error, otherwise - * add MCSV - */ + /* If p == q, no ciphers; caller indicates an error. + * Otherwise, add applicable SCSVs. */ if (p != q) { - static SSL_CIPHER msvc = + if (empty_reneg_info_scsv) { - 0, NULL, SSL3_CK_MCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - j = put_cb ? put_cb(&msvc,p) : ssl_put_cipher_by_char(s,&msvc,p); - p+=j; + static SSL_CIPHER scsv = + { + 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv,p); + p+=j; #ifdef OPENSSL_RI_DEBUG - fprintf(stderr, "MCSV sent by client\n"); + fprintf(stderr, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n"); #endif + } + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) + { + static SSL_CIPHER scsv = + { + 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv,p); + p+=j; + } } return(p-q); @@ -1387,10 +1528,11 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, STACK_OF(SSL_CIPHER) *sk; int i,n; - s->s3->send_connection_binding = 0; + if (s->s3) + s->s3->send_connection_binding = 0; n=ssl_put_cipher_by_char(s,NULL,NULL); - if ((num%n) != 0) + if (n == 0 || (num%n) != 0) { SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); return(NULL); @@ -1403,21 +1545,56 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, sk_SSL_CIPHER_zero(sk); } + if (s->cert->ciphers_raw) + OPENSSL_free(s->cert->ciphers_raw); + s->cert->ciphers_raw = BUF_memdup(p, num); + if (s->cert->ciphers_raw == NULL) + { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + goto err; + } + s->cert->ciphers_rawlen = (size_t)num; + for (i=0; i> 8) & 0xff)) && - (p[n-1] == (SSL3_CK_MCSV & 0xff))) + /* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ + if (s->s3 && (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, "MCSV received by server\n"); + fprintf(stderr, "SCSV received by server\n"); #endif continue; } + /* Check for TLS_FALLBACK_SCSV */ + if ((n != 3 || !p[0]) && + (p[n-2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) && + (p[n-1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) + { + /* The SCSV indicates that the client previously tried a higher version. + * Fail if the current version is an unexpected downgrade. */ + if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) + { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_INAPPROPRIATE_FALLBACK); + if (s->s3) + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INAPPROPRIATE_FALLBACK); + goto err; + } + p += n; + continue; + } + c=ssl_get_cipher_by_char(s,p); p+=n; if (c != NULL) @@ -1461,7 +1638,209 @@ int SSL_get_servername_type(const SSL *s) return TLSEXT_NAMETYPE_host_name; return -1; } -#endif + +/* 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; + } + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* 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 + +/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). + * + * Returns 0 on success. */ +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, + unsigned protos_len) + { + if (ctx->alpn_client_proto_list) + OPENSSL_free(ctx->alpn_client_proto_list); + + ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len); + if (!ctx->alpn_client_proto_list) + return 1; + memcpy(ctx->alpn_client_proto_list, protos, protos_len); + ctx->alpn_client_proto_list_len = protos_len; + + return 0; + } + +/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit + * length-prefixed strings). + * + * Returns 0 on success. */ +int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, + unsigned protos_len) + { + if (ssl->alpn_client_proto_list) + OPENSSL_free(ssl->alpn_client_proto_list); + + ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len); + if (!ssl->alpn_client_proto_list) + return 1; + memcpy(ssl->alpn_client_proto_list, protos, protos_len); + ssl->alpn_client_proto_list_len = protos_len; + + return 0; + } + +/* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called + * during ClientHello processing in order to select an ALPN protocol from the + * client's list of offered protocols. */ +void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), + void *arg) + { + ctx->alpn_select_cb = cb; + ctx->alpn_select_cb_arg = arg; + } + +/* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. + * On return it sets |*data| to point to |*len| bytes of protocol name (not + * including the leading length-prefix byte). If the server didn't respond with + * a negotiated protocol then |*len| will be zero. */ +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len) + { + *data = NULL; + if (ssl->s3) + *data = ssl->s3->alpn_selected; + if (*data == NULL) + *len = 0; + else + *len = ssl->s3->alpn_selected_len; + } + +#endif /* !OPENSSL_NO_TLSEXT */ + +int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, const unsigned char *p, size_t plen, + int use_context) + { + if (s->version < TLS1_VERSION) + return -1; + + return s->method->ssl3_enc->export_keying_material(s, out, olen, label, + llen, p, plen, + use_context); + } static unsigned long ssl_session_hash(const SSL_SESSION *a) { @@ -1506,6 +1885,12 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) return(NULL); } + if (FIPS_mode() && (meth->version < TLS1_VERSION)) + { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + return NULL; + } + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); @@ -1539,9 +1924,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ret->quiet_shutdown=0; /* ret->cipher=NULL;*/ -/* ret->s2->challenge=NULL; +/*- + ret->s2->challenge=NULL; ret->master_key=NULL; - ret->key_arg=NULL; ret->s2->conn_id=NULL; */ ret->info_callback=NULL; @@ -1575,7 +1960,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ssl_create_cipher_list(ret->method, &ret->cipher_list,&ret->cipher_list_by_id, - meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST); + SSL_DEFAULT_CIPHER_LIST, ret->cert); if (ret->cipher_list == NULL || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { @@ -1587,11 +1972,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) if (!ret->param) goto err; - if ((ret->rsa_md5=EVP_get_digestbyname("ssl2-md5")) == NULL) - { - SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES); - goto err2; - } if ((ret->md5=EVP_get_digestbyname("ssl3-md5")) == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES); @@ -1609,7 +1989,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); ret->extra_certs=NULL; - ret->comp_methods=SSL_COMP_get_compression_methods(); + /* No compression for DTLS */ + if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)) + ret->comp_methods=SSL_COMP_get_compression_methods(); ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; @@ -1625,12 +2007,19 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ret->tlsext_status_cb = 0; ret->tlsext_status_arg = NULL; +# ifndef OPENSSL_NO_NEXTPROTONEG + ret->next_protos_advertised_cb = 0; + ret->next_proto_select_cb = 0; +# endif #endif #ifndef OPENSSL_NO_PSK ret->psk_identity_hint=NULL; ret->psk_client_callback=NULL; ret->psk_server_callback=NULL; #endif +#ifndef OPENSSL_NO_SRP + SSL_CTX_SRP_CTX_init(ret); +#endif #ifndef OPENSSL_NO_BUF_FREELISTS ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); @@ -1669,6 +2058,10 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) } #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: @@ -1755,10 +2148,18 @@ void SSL_CTX_free(SSL_CTX *a) a->comp_methods = NULL; #endif +#ifndef OPENSSL_NO_SRTP + if (a->srtp_profiles) + sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); +#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); @@ -1770,6 +2171,16 @@ void SSL_CTX_free(SSL_CTX *a) if (a->rbuf_freelist) ssl_buf_freelist_free(a->rbuf_freelist); #endif +#ifndef OPENSSL_NO_TLSEXT +# ifndef OPENSSL_NO_EC + if (a->tlsext_ecpointformatlist) + OPENSSL_free(a->tlsext_ecpointformatlist); + if (a->tlsext_ellipticcurvelist) + OPENSSL_free(a->tlsext_ellipticcurvelist); +# endif /* OPENSSL_NO_EC */ + if (a->alpn_client_proto_list != NULL) + OPENSSL_free(a->alpn_client_proto_list); +#endif OPENSSL_free(a); } @@ -1801,6 +2212,16 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) X509_VERIFY_PARAM_set_depth(ctx->param, depth); } +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg), void *arg) + { + ssl_cert_set_cert_cb(c->cert, cb, arg); + } + +void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg) + { + ssl_cert_set_cert_cb(s->cert, cb, arg); + } + void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) { CERT_PKEY *cpk; @@ -1808,14 +2229,17 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) int rsa_enc_export,dh_rsa_export,dh_dsa_export; int rsa_tmp_export,dh_tmp_export,kl; unsigned long mask_k,mask_a,emask_k,emask_a; - int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size; +#ifndef OPENSSL_NO_ECDSA + int have_ecc_cert, ecdsa_ok, ecc_pkey_size; +#endif #ifndef OPENSSL_NO_ECDH - int have_ecdh_tmp; + int have_ecdh_tmp, ecdh_ok; #endif +#ifndef OPENSSL_NO_EC X509 *x = NULL; EVP_PKEY *ecc_pkey = NULL; - int signature_nid = 0; - + int signature_nid = 0, pk_nid = 0, md_nid = 0; +#endif if (c == NULL) return; kl=SSL_C_EXPORT_PKEYLENGTH(cipher); @@ -1828,32 +2252,34 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) rsa_tmp=rsa_tmp_export=0; #endif #ifndef OPENSSL_NO_DH - dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL); - dh_tmp_export=(c->dh_tmp_cb != NULL || + dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto); + dh_tmp_export= !c->dh_tmp_auto && (c->dh_tmp_cb != NULL || (dh_tmp && DH_size(c->dh_tmp)*8 <= kl)); #else dh_tmp=dh_tmp_export=0; #endif #ifndef OPENSSL_NO_ECDH - have_ecdh_tmp=(c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL); + have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); #endif cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); - rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); + rsa_enc= cpk->valid_flags & CERT_PKEY_VALID; rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); - rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); + rsa_sign= cpk->valid_flags & CERT_PKEY_SIGN; cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); - dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); + dsa_sign= cpk->valid_flags & CERT_PKEY_SIGN; cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); - dh_rsa= (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_rsa= cpk->valid_flags & CERT_PKEY_VALID; dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_DH_DSA]); /* FIX THIS EAY EAY EAY */ - dh_dsa= (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_dsa= cpk->valid_flags & CERT_PKEY_VALID; 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); +#ifndef OPENSSL_NO_EC + have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID; +#endif mask_k=0; mask_a=0; emask_k=0; @@ -1862,7 +2288,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) #ifdef CIPHER_DEBUG - printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", + fprintf(stderr,"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 @@ -1884,20 +2310,20 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) emask_k|=SSL_kRSA; #if 0 - /* The match needs to be both kEDH and aRSA or aDSA, so don't worry */ + /* The match needs to be both kDHE and aRSA or aDSA, so don't worry */ if ( (dh_tmp || dh_rsa || dh_dsa) && (rsa_enc || rsa_sign || dsa_sign)) - mask_k|=SSL_kEDH; + mask_k|=SSL_kDHE; if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && (rsa_enc || rsa_sign || dsa_sign)) - emask_k|=SSL_kEDH; + emask_k|=SSL_kDHE; #endif if (dh_tmp_export) - emask_k|=SSL_kEDH; + emask_k|=SSL_kDHE; if (dh_tmp) - mask_k|=SSL_kEDH; + mask_k|=SSL_kDHE; if (dh_rsa) mask_k|=SSL_kDHr; if (dh_rsa_export) emask_k|=SSL_kDHr; @@ -1905,6 +2331,9 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) if (dh_dsa) mask_k|=SSL_kDHd; if (dh_dsa_export) emask_k|=SSL_kDHd; + if (emask_k & (SSL_kDHr|SSL_kDHd)) + mask_a |= SSL_aDH; + if (rsa_enc || rsa_sign) { mask_a|=SSL_aRSA; @@ -1930,32 +2359,35 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) /* An ECC certificate may be usable for ECDH and/or * ECDSA cipher suites depending on the key usage extension. */ +#ifndef OPENSSL_NO_EC if (have_ecc_cert) { + cpk = &c->pkeys[SSL_PKEY_ECC]; + x = cpk->x509; /* This call populates extension flags (ex_flags) */ - x = (c->pkeys[SSL_PKEY_ECC]).x509; X509_check_purpose(x, -1, 0); +#ifndef OPENSSL_NO_ECDH ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1; +#endif ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; + if (!(cpk->valid_flags & CERT_PKEY_SIGN)) + ecdsa_ok = 0; ecc_pkey = X509_get_pubkey(x); 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) { - const char *sig = OBJ_nid2ln(signature_nid); - if (sig == NULL) - { - ERR_clear_error(); - sig = "unknown"; - } - - if (strstr(sig, "WithRSA")) + + if (pk_nid == NID_rsaEncryption || pk_nid == NID_rsa) { mask_k|=SSL_kECDHr; mask_a|=SSL_aECDH; @@ -1966,7 +2398,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) } } - if (signature_nid == NID_ecdsa_with_SHA1) + if (pk_nid == NID_X9_62_id_ecPublicKey) { mask_k|=SSL_kECDHe; mask_a|=SSL_aECDH; @@ -1986,12 +2418,13 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) } #endif } +#endif #ifndef OPENSSL_NO_ECDH if (have_ecdh_tmp) { - mask_k|=SSL_kEECDH; - emask_k|=SSL_kEECDH; + mask_k|=SSL_kECDHE; + emask_k|=SSL_kECDHE; } #endif @@ -2015,12 +2448,13 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) #ifndef OPENSSL_NO_EC -int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) { unsigned long alg_k, alg_a; EVP_PKEY *pkey = NULL; int keysize = 0; - int signature_nid = 0; + int signature_nid = 0, md_nid = 0, pk_nid = 0; + const SSL_CIPHER *cs = s->s3->tmp.new_cipher; alg_k = cs->algorithm_mkey; alg_a = cs->algorithm_auth; @@ -2038,7 +2472,10 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) /* This call populates the ex_flags field correctly */ X509_check_purpose(x, -1, 0); if ((x->sig_alg) && (x->sig_alg->algorithm)) + { signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); + 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 */ @@ -2047,26 +2484,20 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT); return 0; } - if (alg_k & SSL_kECDHe) + if ((alg_k & SSL_kECDHe) && TLS1_get_version(s) < TLS1_2_VERSION) { /* signature alg must be ECDSA */ - if (signature_nid != NID_ecdsa_with_SHA1) + if (pk_nid != NID_X9_62_id_ecPublicKey) { SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE); return 0; } } - if (alg_k & SSL_kECDHr) + if ((alg_k & SSL_kECDHr) && TLS1_get_version(s) < TLS1_2_VERSION) { /* signature alg must be RSA */ - const char *sig = OBJ_nid2ln(signature_nid); - if (sig == NULL) - { - ERR_clear_error(); - sig = "unknown"; - } - if (strstr(sig, "WithRSA") == NULL) + 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; @@ -2088,111 +2519,108 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) #endif -/* THIS NEEDS CLEANING UP */ -X509 *ssl_get_server_send_cert(SSL *s) +static int ssl_get_server_cert_index(const SSL *s) + { + int idx; + idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509) + idx = SSL_PKEY_RSA_SIGN; + if (idx == -1) + SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR); + return idx; + } + +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { - unsigned long alg_k,alg_a,mask_k,mask_a; CERT *c; - int i,is_export; + int i; - c=s->cert; + c = s->cert; + if (!s->s3 || !s->s3->tmp.new_cipher) + return NULL; ssl_set_cert_masks(c, s->s3->tmp.new_cipher); - is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); - if (is_export) - { - mask_k = c->export_mask_k; - mask_a = c->export_mask_a; - } - else - { - mask_k = c->mask_k; - mask_a = c->mask_a; - } - - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - alg_a = s->s3->tmp.new_cipher->algorithm_auth; - - if (alg_k & (SSL_kECDHr|SSL_kECDHe)) - { - /* we don't need to look at SSL_kEECDH - * since no certificate is needed for - * anon ECDH and for authenticated - * 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 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 (alg_a & SSL_aECDSA) - { - i=SSL_PKEY_ECC; - } - else if (alg_k & SSL_kDHr) - i=SSL_PKEY_DH_RSA; - else if (alg_k & SSL_kDHd) - i=SSL_PKEY_DH_DSA; - else if (alg_a & SSL_aDSS) - i=SSL_PKEY_DSA_SIGN; - 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 (alg_a & SSL_aKRB5) - { - /* VRS something else here? */ - return(NULL); - } - 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); - } - if (c->pkeys[i].x509 == NULL) return(NULL); - return(c->pkeys[i].x509); +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* Broken protocol test: return last used certificate: which may + * mismatch the one expected. + */ + if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) + return c->key; +#endif + + i = ssl_get_server_cert_index(s); + + /* This may or may not be an error. */ + if (i < 0) + return NULL; + + /* May be NULL. */ + return &c->pkeys[i]; } -EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher) +EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) { unsigned long alg_a; CERT *c; + int idx = -1; alg_a = cipher->algorithm_auth; c=s->cert; +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + /* Broken protocol test: use last key: which may + * mismatch the one expected. + */ + if (c->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) + idx = c->key - c->pkeys; + else +#endif + if ((alg_a & SSL_aDSS) && (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) - return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); + idx = SSL_PKEY_DSA_SIGN; else if (alg_a & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) - return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey); + idx = SSL_PKEY_RSA_SIGN; else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) - return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey); - else - return(NULL); + idx = SSL_PKEY_RSA_ENC; } else if ((alg_a & SSL_aECDSA) && (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) - return(c->pkeys[SSL_PKEY_ECC].privatekey); - else /* if (alg_a & SSL_aNULL) */ + idx = SSL_PKEY_ECC; + if (idx == -1) { SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); return(NULL); } + if (pmd) + *pmd = c->pkeys[idx].digest; + return c->pkeys[idx].privatekey; } +#ifndef OPENSSL_NO_TLSEXT +int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, + size_t *serverinfo_length) + { + CERT *c = NULL; + int i = 0; + *serverinfo_length = 0; + + c = s->cert; + i = ssl_get_server_cert_index(s); + + if (i == -1) + return 0; + if (c->pkeys[i].serverinfo == NULL) + return 0; + + *serverinfo = c->pkeys[i].serverinfo; + *serverinfo_length = c->pkeys[i].serverinfo_length; + return 1; + } +#endif + void ssl_update_cache(SSL *s,int mode) { int i; @@ -2225,6 +2653,11 @@ void ssl_update_cache(SSL *s,int mode) } } +const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx) + { + return ctx->method; + } + const SSL_METHOD *SSL_get_ssl_method(SSL *s) { return(s->method); @@ -2329,17 +2762,9 @@ int SSL_get_error(const SSL *s,int i) if (i == 0) { - if (s->version == SSL2_VERSION) - { - /* assume it is the socket being closed */ + if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) return(SSL_ERROR_ZERO_RETURN); - } - else - { - if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && - (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) - return(SSL_ERROR_ZERO_RETURN); - } } return(SSL_ERROR_SYSCALL); } @@ -2415,14 +2840,14 @@ SSL_METHOD *ssl_bad_method(int ver) const char *SSL_get_version(const SSL *s) { - if (s->version == TLS1_1_VERSION) + if (s->version == TLS1_2_VERSION) + return("TLSv1.2"); + else 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"); - else if (s->version == SSL3_VERSION) - return("SSLv3"); - else if (s->version == SSL2_VERSION) - return("SSLv2"); else return("unknown"); } @@ -2511,6 +2936,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; @@ -2585,7 +3011,6 @@ void ssl_clear_cipher_ctx(SSL *s) #endif } -/* Fix this function so that it takes an optional type parameter */ X509 *SSL_get_certificate(const SSL *s) { if (s->cert != NULL) @@ -2594,8 +3019,7 @@ X509 *SSL_get_certificate(const SSL *s) return(NULL); } -/* Fix this function so that it takes an optional type parameter */ -EVP_PKEY *SSL_get_privatekey(SSL *s) +EVP_PKEY *SSL_get_privatekey(const SSL *s) { if (s->cert != NULL) return(s->cert->key->privatekey); @@ -2603,6 +3027,22 @@ EVP_PKEY *SSL_get_privatekey(SSL *s) return(NULL); } +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) + { + if (ctx->cert != NULL) + return ctx->cert->key->x509; + else + return NULL; + } + +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) + { + if (ctx->cert != NULL) + return ctx->cert->key->privatekey; + else + return NULL ; + } + const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) { if ((s->session != NULL) && (s->session->cipher != NULL)) @@ -2729,19 +3169,54 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) { + CERT *ocert = ssl->cert; 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); + if (ocert) + { + /* Preserve any already negotiated parameters */ + if (ssl->server) + { + ssl->cert->peer_sigalgs = ocert->peer_sigalgs; + ssl->cert->peer_sigalgslen = ocert->peer_sigalgslen; + ocert->peer_sigalgs = NULL; + ssl->cert->ciphers_raw = ocert->ciphers_raw; + ssl->cert->ciphers_rawlen = ocert->ciphers_rawlen; + ocert->ciphers_raw = NULL; + } + ssl_cert_free(ocert); + } + + /* + * Program invariant: |sid_ctx| has fixed size (SSL_MAX_SID_CTX_LENGTH), + * so setter APIs must prevent invalid lengths from entering the system. + */ + OPENSSL_assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx)); + + /* + * If the session ID context matches that of the parent SSL_CTX, + * inherit it from the new SSL_CTX as well. If however the context does + * not match (i.e., it was set per-ssl with SSL_set_session_id_context), + * leave it unchanged. + */ + if ((ssl->ctx != NULL) && + (ssl->sid_ctx_length == ssl->ctx->sid_ctx_length) && + (memcmp(ssl->sid_ctx, ssl->ctx->sid_ctx, ssl->sid_ctx_length) == 0)) + { + ssl->sid_ctx_length = ctx->sid_ctx_length; + memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx)); + } + 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); } @@ -2776,6 +3251,11 @@ int SSL_state(const SSL *ssl) return(ssl->state); } +void SSL_set_state(SSL *ssl, int state) + { + ssl->state = state; + } + void SSL_set_verify_result(SSL *ssl,long arg) { ssl->verify_result=arg; @@ -3014,6 +3494,19 @@ 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 @@ -3034,6 +3527,81 @@ void ssl_clear_hash_ctx(EVP_MD_CTX **hash) *hash=NULL; } +void SSL_set_debug(SSL *s, int debug) + { + s->debug = debug; + } + +int SSL_cache_hit(SSL *s) + { + return s->hit; + } + +int SSL_is_server(SSL *s) + { + return s->server; + } + +void SSL_set_security_level(SSL *s, int level) + { + s->cert->sec_level = level; + } + +int SSL_get_security_level(const SSL *s) + { + return s->cert->sec_level; + } + +void SSL_set_security_callback(SSL *s, int (*cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex)) + { + s->cert->sec_cb = cb; + } + +int (*SSL_get_security_callback(const SSL *s))(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex) + { + return s->cert->sec_cb; + } + +void SSL_set0_security_ex_data(SSL *s, void *ex) + { + s->cert->sec_ex = ex; + } + +void *SSL_get0_security_ex_data(const SSL *s) + { + return s->cert->sec_ex; + } + +void SSL_CTX_set_security_level(SSL_CTX *ctx, int level) + { + ctx->cert->sec_level = level; + } + +int SSL_CTX_get_security_level(const SSL_CTX *ctx) + { + return ctx->cert->sec_level; + } + +void SSL_CTX_set_security_callback(SSL_CTX *ctx, int (*cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex)) + { + ctx->cert->sec_cb = cb; + } + +int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx))(SSL *s, SSL_CTX *ctx, int op, int bits, int nid, void *other, void *ex) + { + return ctx->cert->sec_cb; + } + +void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex) + { + ctx->cert->sec_ex = ex; + } + +void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx) + { + return ctx->cert->sec_ex; + } + #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) #include "../crypto/bio/bss_file.c" #endif @@ -3042,4 +3610,3 @@ IMPLEMENT_STACK_OF(SSL_CIPHER) IMPLEMENT_STACK_OF(SSL_COMP) IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); -