X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=cc9b965778e5bcf4e13e1930823d1dfa394d038f;hp=18e80d4ddc70f3011ffd2d38f2c011bd9ba1de11;hb=09599b52d4e295c380512ba39958a11994d63401;hpb=18d7158809c9722f4c6d2a8af7513577274f9b56 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 18e80d4ddc..cc9b965778 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -263,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); + meth->version == SSL2_VERSION ? "SSLv2" : 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); @@ -382,6 +382,17 @@ SSL *SSL_new(SSL_CTX *ctx) # 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; @@ -525,6 +536,16 @@ 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); @@ -606,6 +627,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) @@ -1112,8 +1135,7 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) return 0; #endif - if (SSL_version(s) == DTLS1_VERSION || - SSL_version(s) == DTLS1_BAD_VER) + if (SSL_IS_DTLS(s)) { s->d1->mtu = larg; return larg; @@ -1132,6 +1154,17 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) 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)); } @@ -1158,6 +1191,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) { @@ -1333,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 @@ -1357,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; @@ -1410,10 +1459,11 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, { int i,j=0; SSL_CIPHER *c; + CERT *ct = s->cert; unsigned char *q; -#ifndef OPENSSL_NO_KRB5 - int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx); -#endif /* OPENSSL_NO_KRB5 */ + int no_scsv = s->renegotiate; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); if (sk == NULL) return(0); q=p; @@ -1421,28 +1471,27 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, for (i=0; ialgorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_client_version(s) < TLS1_2_VERSION)) - continue; -#ifndef 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) + /* Skip disabled ciphers */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || + c->algorithm_auth & ct->mask_a) continue; -#endif /* OPENSSL_NO_PSK */ +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (c->id == SSL3_CK_SCSV) + { + if (no_scsv) + continue; + else + no_scsv = 1; + } +#endif 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) + if (p != q && !no_scsv) { static SSL_CIPHER scsv = { @@ -1481,6 +1530,16 @@ 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; inext_proto_select_cb_arg = arg; } # endif -#endif + +int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, + custom_cli_ext_first_cb_fn fn1, + custom_cli_ext_second_cb_fn fn2, void* arg) + { + size_t i; + custom_cli_ext_record* record; + + /* Check for duplicates */ + for (i=0; i < ctx->custom_cli_ext_records_count; i++) + if (ext_type == ctx->custom_cli_ext_records[i].ext_type) + return 0; + + ctx->custom_cli_ext_records = OPENSSL_realloc(ctx->custom_cli_ext_records, + (ctx->custom_cli_ext_records_count + 1) * + sizeof(custom_cli_ext_record)); + if (!ctx->custom_cli_ext_records) { + ctx->custom_cli_ext_records_count = 0; + return 0; + } + ctx->custom_cli_ext_records_count++; + record = &ctx->custom_cli_ext_records[ctx->custom_cli_ext_records_count - 1]; + record->ext_type = ext_type; + record->fn1 = fn1; + record->fn2 = fn2; + record->arg = arg; + return 1; + } + +int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, + custom_srv_ext_first_cb_fn fn1, + custom_srv_ext_second_cb_fn fn2, void* arg) + { + size_t i; + custom_srv_ext_record* record; + + /* Check for duplicates */ + for (i=0; i < ctx->custom_srv_ext_records_count; i++) + if (ext_type == ctx->custom_srv_ext_records[i].ext_type) + return 0; + + ctx->custom_srv_ext_records = OPENSSL_realloc(ctx->custom_srv_ext_records, + (ctx->custom_srv_ext_records_count + 1) * + sizeof(custom_srv_ext_record)); + if (!ctx->custom_srv_ext_records) { + ctx->custom_srv_ext_records_count = 0; + return 0; + } + ctx->custom_srv_ext_records_count++; + record = &ctx->custom_srv_ext_records[ctx->custom_srv_ext_records_count - 1]; + record->ext_type = ext_type; + record->fn1 = fn1; + record->fn2 = fn2; + record->arg = arg; + return 1; + } + +/* 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; + } + +int SSL_CTX_set_cli_supp_data(SSL_CTX *ctx, + unsigned short supp_data_type, + cli_supp_data_first_cb_fn fn1, + cli_supp_data_second_cb_fn fn2, void* arg) + { + size_t i; + cli_supp_data_record* record; + + /* Check for duplicates */ + for (i=0; i < ctx->cli_supp_data_records_count; i++) + if (supp_data_type == ctx->cli_supp_data_records[i].supp_data_type) + return 0; + + ctx->cli_supp_data_records = OPENSSL_realloc(ctx->cli_supp_data_records, + (ctx->cli_supp_data_records_count+1) * sizeof(cli_supp_data_record)); + if (!ctx->cli_supp_data_records) + { + ctx->cli_supp_data_records_count = 0; + return 0; + } + ctx->cli_supp_data_records_count++; + record = &ctx->cli_supp_data_records[ctx->cli_supp_data_records_count - 1]; + record->supp_data_type = supp_data_type; + record->fn1 = fn1; + record->fn2 = fn2; + record->arg = arg; + return 1; + } + +int SSL_CTX_set_srv_supp_data(SSL_CTX *ctx, + unsigned short supp_data_type, + srv_supp_data_first_cb_fn fn1, + srv_supp_data_second_cb_fn fn2, void* arg) + { + size_t i; + srv_supp_data_record* record; + + /* Check for duplicates */ + for (i=0; i < ctx->srv_supp_data_records_count; i++) + if (supp_data_type == ctx->srv_supp_data_records[i].supp_data_type) + return 0; + + ctx->srv_supp_data_records = OPENSSL_realloc(ctx->srv_supp_data_records, + (ctx->srv_supp_data_records_count+1) * sizeof(srv_supp_data_record)); + if (!ctx->srv_supp_data_records) + { + ctx->srv_supp_data_records_count = 0; + return 0; + } + ctx->srv_supp_data_records_count++; + record = &ctx->srv_supp_data_records[ctx->srv_supp_data_records_count - 1]; + record->supp_data_type = supp_data_type; + record->fn1 = fn1; + record->fn2 = fn2; + record->arg = arg; + + return 1; + } + +#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, @@ -1797,7 +2044,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); + meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ret->cert); if (ret->cipher_list == NULL || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { @@ -1831,7 +2078,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; @@ -1860,6 +2109,14 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) #ifndef OPENSSL_NO_SRP SSL_CTX_SRP_CTX_init(ret); #endif + ret->custom_cli_ext_records = NULL; + ret->custom_cli_ext_records_count = 0; + ret->custom_srv_ext_records = NULL; + ret->custom_srv_ext_records_count = 0; + ret->cli_supp_data_records = NULL; + ret->cli_supp_data_records_count = 0; + ret->srv_supp_data_records = NULL; + ret->srv_supp_data_records_count = 0; #ifndef OPENSSL_NO_BUF_FREELISTS ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); @@ -1998,6 +2255,12 @@ void SSL_CTX_free(SSL_CTX *a) #ifndef OPENSSL_NO_SRP SSL_CTX_SRP_CTX_free(a); #endif +#ifndef OPENSSL_NO_TLSEXT + OPENSSL_free(a->custom_cli_ext_records); + OPENSSL_free(a->custom_srv_ext_records); + OPENSSL_free(a->cli_supp_data_records); + OPENSSL_free(a->srv_supp_data_records); +#endif #ifndef OPENSSL_NO_ENGINE if (a->client_cert_engine) ENGINE_finish(a->client_cert_engine); @@ -2016,6 +2279,8 @@ void SSL_CTX_free(SSL_CTX *a) 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); @@ -2065,14 +2330,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, pk_nid = 0, md_nid = 0; - +#endif if (c == NULL) return; kl=SSL_C_EXPORT_PKEYLENGTH(cipher); @@ -2085,8 +2353,8 @@ 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; @@ -2096,21 +2364,23 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) 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->valid_flags; + 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->valid_flags & CERT_PKEY_SIGN); + rsa_sign= cpk->valid_flags & CERT_PKEY_SIGN; cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); - dsa_sign= (cpk->valid_flags & CERT_PKEY_SIGN); + dsa_sign= cpk->valid_flags & CERT_PKEY_SIGN; cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); - dh_rsa= cpk->valid_flags; + 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->valid_flags; + 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->valid_flags; +#ifndef OPENSSL_NO_EC + have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID; +#endif mask_k=0; mask_a=0; emask_k=0; @@ -2141,20 +2411,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; @@ -2190,6 +2460,7 @@ 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]; @@ -2246,12 +2517,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 @@ -2346,66 +2618,35 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) #endif -/* THIS NEEDS CLEANING UP */ -static int ssl_get_server_cert_index(SSL *s) +static int ssl_get_server_cert_index(const SSL *s) { - unsigned long alg_k, alg_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. - */ - return SSL_PKEY_ECC; - } - else if (alg_a & SSL_aECDSA) - return SSL_PKEY_ECC; - else if (alg_k & SSL_kDHr) - return SSL_PKEY_DH_RSA; - else if (alg_k & SSL_kDHd) - return SSL_PKEY_DH_DSA; - else if (alg_a & SSL_aDSS) - return SSL_PKEY_DSA_SIGN; - else if (alg_a & SSL_aRSA) - { - if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) - return SSL_PKEY_RSA_SIGN; - else - return SSL_PKEY_RSA_ENC; - } - else if (alg_a & SSL_aKRB5) - /* VRS something else here? */ - return -1; - else if (alg_a & SSL_aGOST94) - return SSL_PKEY_GOST94; - else if (alg_a & SSL_aGOST01) - return SSL_PKEY_GOST01; - else /* if (alg_a & SSL_aNULL) */ - { + 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 -1; - } + return idx; } -CERT_PKEY *ssl_get_server_send_pkey(SSL *s) +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { CERT *c; int i; c = s->cert; + if (!s->s3 || !s->s3->tmp.new_cipher) + return NULL; ssl_set_cert_masks(c, s->s3->tmp.new_cipher); +#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. */ @@ -2425,6 +2666,15 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) 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)) idx = SSL_PKEY_DSA_SIGN; @@ -2449,23 +2699,24 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) } #ifndef OPENSSL_NO_TLSEXT -unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length) +int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, + size_t *serverinfo_length) { - CERT *c; - int i; + CERT *c = NULL; + int i = 0; + *serverinfo_length = 0; c = s->cert; i = ssl_get_server_cert_index(s); if (i == -1) - return NULL; - - *authz_length = 0; - if (c->pkeys[i].authz == NULL) - return(NULL); - *authz_length = c->pkeys[i].authz_length; + return 0; + if (c->pkeys[i].serverinfo == NULL) + return 0; - return c->pkeys[i].authz; + *serverinfo = c->pkeys[i].serverinfo; + *serverinfo_length = c->pkeys[i].serverinfo_length; + return 1; } #endif @@ -2501,6 +2752,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); @@ -2864,7 +3120,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) @@ -2873,8 +3128,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); @@ -2882,6 +3136,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)) @@ -3341,6 +3611,11 @@ int SSL_cache_hit(SSL *s) return s->hit; } +int SSL_is_server(SSL *s) + { + return s->server; + } + #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) #include "../crypto/bio/bss_file.c" #endif