diff options
Diffstat (limited to 'app/openssl/ssl/ssl_lib.c')
-rw-r--r-- | app/openssl/ssl/ssl_lib.c | 323 |
1 files changed, 273 insertions, 50 deletions
diff --git a/app/openssl/ssl/ssl_lib.c b/app/openssl/ssl/ssl_lib.c index b169ba93..8d2c3a76 100644 --- a/app/openssl/ssl/ssl_lib.c +++ b/app/openssl/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; @@ -357,6 +360,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; @@ -374,6 +388,13 @@ SSL *SSL_new(SSL_CTX *ctx) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); #ifndef OPENSSL_NO_PSK + s->psk_identity_hint = NULL; + if (ctx->psk_identity_hint) + { + s->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint); + if (s->psk_identity_hint == NULL) + goto err; + } s->psk_client_callback=ctx->psk_client_callback; s->psk_server_callback=ctx->psk_server_callback; #endif @@ -576,6 +597,15 @@ 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->tlsext_channel_id_private) + EVP_PKEY_free(s->tlsext_channel_id_private); + if (s->alpn_client_proto_list) + OPENSSL_free(s->alpn_client_proto_list); +#endif + +#ifndef OPENSSL_NO_PSK + if (s->psk_identity_hint) + OPENSSL_free(s->psk_identity_hint); #endif if (s->client_CA != NULL) @@ -595,6 +625,11 @@ void SSL_free(SSL *s) 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); } @@ -1017,10 +1052,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)); } @@ -1028,7 +1074,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) @@ -1063,6 +1109,11 @@ 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) { @@ -1390,6 +1441,10 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { c=sk_SSL_CIPHER_value(sk,i); + /* Skip TLS v1.2 only ciphersuites if lower than v1.2 */ + if ((c->algorithm_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) @@ -1397,7 +1452,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, #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)) && + if ((c->algorithm_auth & SSL_aPSK) && s->psk_client_callback == NULL) continue; #endif /* OPENSSL_NO_PSK */ @@ -1407,7 +1462,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, /* If p == q, no ciphers and caller indicates an error. Otherwise * add SCSV if not renegotiating. */ - if (p != q && !s->new_session) + if (p != q && !s->renegotiate) { static SSL_CIPHER scsv = { @@ -1454,7 +1509,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, (p[n-1] == (SSL3_CK_SCSV & 0xff))) { /* SCSV fatal if renegotiating */ - if (s->new_session) + 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); @@ -1627,10 +1682,93 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned 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 +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; @@ -1674,6 +1812,14 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) return(NULL); } +#ifdef OPENSSL_FIPS + if (FIPS_mode() && (meth->version < TLS1_VERSION)) + { + SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + return NULL; + } +#endif + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); @@ -1777,7 +1923,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->version != DTLS1_VERSION) + ret->comp_methods=SSL_COMP_get_compression_methods(); ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; @@ -1803,6 +1951,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) 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)); @@ -1931,10 +2082,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); @@ -1947,6 +2106,13 @@ void SSL_CTX_free(SSL_CTX *a) ssl_buf_freelist_free(a->rbuf_freelist); #endif +#ifndef OPENSSL_NO_TLSEXT + if (a->tlsext_channel_id_private) + EVP_PKEY_free(a->tlsext_channel_id_private); + if (a->alpn_client_proto_list != NULL) + OPENSSL_free(a->alpn_client_proto_list); +#endif + OPENSSL_free(a); } @@ -2188,12 +2354,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, 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; @@ -2223,7 +2390,7 @@ 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 (pk_nid != NID_X9_62_id_ecPublicKey) @@ -2232,7 +2399,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs) return 0; } } - if (alg_k & SSL_kECDHr) + if ((alg_k & SSL_kECDHr) && TLS1_get_version(s) < TLS1_2_VERSION) { /* signature alg must be RSA */ @@ -2259,7 +2426,7 @@ 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) +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { unsigned long alg_k,alg_a; CERT *c; @@ -2314,15 +2481,23 @@ X509 *ssl_get_server_send_cert(SSL *s) i=SSL_PKEY_GOST01; else /* if (alg_a & SSL_aNULL) */ { - SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY,ERR_R_INTERNAL_ERROR); return(NULL); } - if (c->pkeys[i].x509 == NULL) return(NULL); - return(c->pkeys[i].x509); + return c->pkeys + i; + } + +X509 *ssl_get_server_send_cert(const SSL *s) + { + CERT_PKEY *cpk; + cpk = ssl_get_server_send_pkey(s); + if (!cpk) + return NULL; + return cpk->x509; } -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; @@ -2330,26 +2505,37 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher) alg_a = cipher->algorithm_auth; c=s->cert; + /* SHA1 is the default for all signature algorithms up to TLS 1.2, + * except RSA which is handled specially in s3_srvr.c */ + if (pmd) + *pmd = EVP_sha1(); + if ((alg_a & SSL_aDSS) && - (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) - return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); + (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) + { + if (pmd && s->s3 && s->s3->digest_dsa) + *pmd = s->s3->digest_dsa; + return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey; + } else if (alg_a & SSL_aRSA) { + if (pmd && s->s3 && s->s3->digest_rsa) + *pmd = s->s3->digest_rsa; if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) - return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey); - else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) - return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey); - else - return(NULL); + return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey; + if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) + return c->pkeys[SSL_PKEY_RSA_ENC].privatekey; } 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) */ { - SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); - return(NULL); + if (pmd && s->s3 && s->s3->digest_ecdsa) + *pmd = s->s3->digest_ecdsa; + return c->pkeys[SSL_PKEY_ECC].privatekey; } + + SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); + return(NULL); } void ssl_update_cache(SSL *s,int mode) @@ -2574,7 +2760,11 @@ SSL_METHOD *ssl_bad_method(int ver) static const char *ssl_get_version(int version) { - if (version == TLS1_VERSION) + if (version == TLS1_2_VERSION) + return("TLSv1.2"); + else if (version == TLS1_1_VERSION) + return("TLSv1.1"); + else if (version == TLS1_VERSION) return("TLSv1"); else if (version == SSL3_VERSION) return("SSLv3"); @@ -2602,12 +2792,8 @@ const char* SSL_authentication_method(const SSL* ssl) { case SSL2_VERSION: return SSL_TXT_RSA; - case SSL3_VERSION: - case TLS1_VERSION: - case DTLS1_VERSION: - return SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher); default: - return "UNKNOWN"; + return SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher); } } @@ -2695,6 +2881,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; @@ -2960,6 +3147,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; @@ -3123,32 +3315,54 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) if (s == NULL) return 0; - if (s->session == NULL) - return 1; /* session not created yet, ignored */ - if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); return 0; } - if (s->session->psk_identity_hint != NULL) + + /* Clear hint in SSL and associated SSL_SESSION (if any). */ + if (s->psk_identity_hint != NULL) + { + OPENSSL_free(s->psk_identity_hint); + s->psk_identity_hint = NULL; + } + if (s->session != NULL && s->session->psk_identity_hint != NULL) + { OPENSSL_free(s->session->psk_identity_hint); + s->session->psk_identity_hint = NULL; + } + if (identity_hint != NULL) { - s->session->psk_identity_hint = BUF_strdup(identity_hint); - if (s->session->psk_identity_hint == NULL) - return 0; + /* The hint is stored in SSL and SSL_SESSION with the one in + * SSL_SESSION taking precedence. Thus, if SSL_SESSION is avaiable, + * we store the hint there, otherwise we store it in SSL. */ + if (s->session != NULL) + { + s->session->psk_identity_hint = BUF_strdup(identity_hint); + if (s->session->psk_identity_hint == NULL) + return 0; + } + else + { + s->psk_identity_hint = BUF_strdup(identity_hint); + if (s->psk_identity_hint == NULL) + return 0; + } } - else - s->session->psk_identity_hint = NULL; return 1; } const char *SSL_get_psk_identity_hint(const SSL *s) { - if (s == NULL || s->session == NULL) + if (s == NULL) return NULL; - return(s->session->psk_identity_hint); + /* The hint is stored in SSL and SSL_SESSION with the one in SSL_SESSION + * taking precedence. */ + if (s->session != NULL) + return(s->session->psk_identity_hint); + return(s->psk_identity_hint); } const char *SSL_get_psk_identity(const SSL *s) @@ -3231,6 +3445,16 @@ 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; + } + #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) #include "../crypto/bio/bss_file.c" #endif @@ -3239,4 +3463,3 @@ IMPLEMENT_STACK_OF(SSL_CIPHER) IMPLEMENT_STACK_OF(SSL_COMP) IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); - |