X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fssl_lib.c;h=555a630b1ba8da6e316c2e2ed5b6111c37135e8b;hb=da8512aaffe3580e3701198ef9eba2471c5edbc2;hp=ee84bb78d87e155cb1c12a1456c1c346bc53b796;hpb=b08b158b44e3bcd5afddf9b1b79362fe4a309821;p=oweals%2Fopenssl.git diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index ee84bb78d8..555a630b1b 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) @@ -353,6 +356,31 @@ 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 #endif s->verify_result=X509_V_OK; @@ -586,6 +614,14 @@ 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 + + if (s->srtp_profiles) + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); + OPENSSL_free(s); } @@ -1065,8 +1101,10 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) s->max_cert_list=larg; return(l); case SSL_CTRL_SET_MTU: +#ifndef OPENSSL_NO_DTLS1 if (larg < (long)dtls1_min_mtu()) return 0; +#endif if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) @@ -1494,8 +1532,137 @@ int SSL_get_servername_type(const SSL *s) 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 +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) { unsigned long l; @@ -1666,6 +1833,10 @@ 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; @@ -1717,8 +1888,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) * deployed might change this. */ ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; - /* Disable TLS v1.2 by default for now */ - ret->options |= SSL_OP_NO_TLSv1_2; return(ret); err: @@ -1805,6 +1974,9 @@ void SSL_CTX_free(SSL_CTX *a) a->comp_methods = NULL; #endif + if (a->srtp_profiles) + sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); + #ifndef OPENSSL_NO_PSK if (a->psk_identity_hint) OPENSSL_free(a->psk_identity_hint); @@ -1822,6 +1994,14 @@ void SSL_CTX_free(SSL_CTX *a) ssl_buf_freelist_free(a->wbuf_freelist); 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 */ #endif OPENSSL_free(a); @@ -1889,7 +2069,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher) #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); @@ -1958,6 +2138,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; @@ -2137,15 +2320,10 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) #endif /* THIS NEEDS CLEANING UP */ -X509 *ssl_get_server_send_cert(SSL *s) +static int ssl_get_server_cert_index(const SSL *s) { - unsigned long alg_k,alg_a; - CERT *c; - int i; + unsigned long alg_k, alg_a; - c=s->cert; - ssl_set_cert_masks(c, s->s3->tmp.new_cipher); - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -2162,42 +2340,53 @@ X509 *ssl_get_server_send_cert(SSL *s) * checks for SSL_kECDH before RSA * checks ensures the correct cert is chosen. */ - i=SSL_PKEY_ECC; + return SSL_PKEY_ECC; } else if (alg_a & SSL_aECDSA) - { - i=SSL_PKEY_ECC; - } + return SSL_PKEY_ECC; else if (alg_k & SSL_kDHr) - i=SSL_PKEY_DH_RSA; + return SSL_PKEY_DH_RSA; else if (alg_k & SSL_kDHd) - i=SSL_PKEY_DH_DSA; + return SSL_PKEY_DH_DSA; else if (alg_a & SSL_aDSS) - i=SSL_PKEY_DSA_SIGN; + return SSL_PKEY_DSA_SIGN; else if (alg_a & SSL_aRSA) { - if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) - i=SSL_PKEY_RSA_SIGN; + if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) + return SSL_PKEY_RSA_SIGN; else - i=SSL_PKEY_RSA_ENC; + return SSL_PKEY_RSA_ENC; } else if (alg_a & SSL_aKRB5) - { /* VRS something else here? */ - return(NULL); - } + return -1; else if (alg_a & SSL_aGOST94) - i=SSL_PKEY_GOST94; + return SSL_PKEY_GOST94; else if (alg_a & SSL_aGOST01) - i=SSL_PKEY_GOST01; + return SSL_PKEY_GOST01; else /* if (alg_a & SSL_aNULL) */ { - SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR); - return(NULL); + SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR); + return -1; } - if (c->pkeys[i].x509 == NULL) return(NULL); + } + +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) + { + CERT *c; + int i; + + c = s->cert; + ssl_set_cert_masks(c, s->s3->tmp.new_cipher); + + i = ssl_get_server_cert_index(s); + + /* This may or may not be an error. */ + if (i < 0) + return NULL; - return(c->pkeys[i].x509); + /* May be NULL. */ + return &c->pkeys[i]; } EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) @@ -2232,6 +2421,27 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) return c->pkeys[idx].privatekey; } +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length) + { + CERT *c; + int i; + + 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 c->pkeys[i].authz; + } +#endif + void ssl_update_cache(SSL *s,int mode) { int i; @@ -2458,7 +2668,7 @@ const char *SSL_get_version(const SSL *s) return("TLSv1.2"); else if (s->version == TLS1_1_VERSION) return("TLSv1.1"); - if (s->version == TLS1_VERSION) + else if (s->version == TLS1_VERSION) return("TLSv1"); else if (s->version == SSL3_VERSION) return("SSLv3"); @@ -2630,6 +2840,14 @@ void ssl_clear_cipher_ctx(SSL *s) /* Fix this function so that it takes an optional type parameter */ X509 *SSL_get_certificate(const SSL *s) { + if (s->server) + { + CERT_PKEY *certpkey; + certpkey = ssl_get_server_send_pkey(s); + if (certpkey && certpkey->x509) + return certpkey->x509; + } + if (s->cert != NULL) return(s->cert->key->x509); else