X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=c6ca1379a0cc34fb0b843c97d877fe2e6c4a583c;hp=c3b40323687cd0ddbd733044b83319150f00c9a8;hb=77a926e6769705944e8ac8db37650cd36161be97;hpb=2f0275a4c3c8921e51d5c0ceb64a71d53dda5da0 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index c3b4032368..c6ca1379a0 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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) @@ -1173,8 +1196,10 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) { 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); @@ -1317,6 +1342,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) @@ -1434,7 +1486,6 @@ 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; int no_scsv = s->renegotiate; /* Set disabled masks for this session */ @@ -1447,9 +1498,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, { c=sk_SSL_CIPHER_value(sk,i); /* Skip disabled ciphers */ - if (c->algorithm_ssl & ct->mask_ssl || - c->algorithm_mkey & ct->mask_k || - c->algorithm_auth & ct->mask_a) + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) continue; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL if (c->id == SSL3_CK_SCSV) @@ -1581,7 +1630,6 @@ int SSL_get_servername_type(const SSL *s) 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. @@ -1648,6 +1696,7 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsi 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. @@ -1697,7 +1746,195 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned ctx->next_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, @@ -1896,6 +2133,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)); @@ -2034,6 +2279,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); @@ -2052,6 +2303,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); @@ -2101,14 +2354,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); @@ -2121,8 +2377,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; @@ -2146,7 +2402,9 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) 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]); +#ifndef OPENSSL_NO_EC have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID; +#endif mask_k=0; mask_a=0; emask_k=0; @@ -2177,20 +2435,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; @@ -2226,6 +2484,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]; @@ -2282,12 +2541,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 @@ -2399,6 +2659,8 @@ CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) 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 @@ -2461,23 +2723,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 @@ -2513,6 +2776,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); @@ -2876,7 +3144,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) @@ -2885,8 +3152,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); @@ -2894,6 +3160,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)) @@ -3358,6 +3640,67 @@ 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