📄 ssl_lib.c
字号:
CERT_PKEY *cpk; int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign; int rsa_enc_export,dh_rsa_export,dh_dsa_export; int rsa_tmp_export,dh_tmp_export,kl; unsigned long mask,emask; int have_ecc_cert, ecdh_ok, ecdsa_ok, ecc_pkey_size;#ifndef OPENSSL_NO_ECDH int have_ecdh_tmp;#endif X509 *x = NULL; EVP_PKEY *ecc_pkey = NULL; int signature_nid = 0; if (c == NULL) return; kl=SSL_C_EXPORT_PKEYLENGTH(cipher);#ifndef OPENSSL_NO_RSA rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL); rsa_tmp_export=(c->rsa_tmp_cb != NULL || (rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl));#else 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 && 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);#endif cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); 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); cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); dh_rsa= (cpk->x509 != NULL && cpk->privatekey != NULL); 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_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); mask=0; emask=0;#ifdef CIPHER_DEBUG printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", rsa_tmp,rsa_tmp_export,dh_tmp, rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);#endif if (rsa_enc || (rsa_tmp && rsa_sign)) mask|=SSL_kRSA; if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc))) emask|=SSL_kRSA;#if 0 /* The match needs to be both kEDH and aRSA or aDSA, so don't worry */ if ( (dh_tmp || dh_rsa || dh_dsa) && (rsa_enc || rsa_sign || dsa_sign)) mask|=SSL_kEDH; if ((dh_tmp_export || dh_rsa_export || dh_dsa_export) && (rsa_enc || rsa_sign || dsa_sign)) emask|=SSL_kEDH;#endif if (dh_tmp_export) emask|=SSL_kEDH; if (dh_tmp) mask|=SSL_kEDH; if (dh_rsa) mask|=SSL_kDHr; if (dh_rsa_export) emask|=SSL_kDHr; if (dh_dsa) mask|=SSL_kDHd; if (dh_dsa_export) emask|=SSL_kDHd; if (rsa_enc || rsa_sign) { mask|=SSL_aRSA; emask|=SSL_aRSA; } if (dsa_sign) { mask|=SSL_aDSS; emask|=SSL_aDSS; } mask|=SSL_aNULL; emask|=SSL_aNULL;#ifndef OPENSSL_NO_KRB5 mask|=SSL_kKRB5|SSL_aKRB5; emask|=SSL_kKRB5|SSL_aKRB5;#endif /* An ECC certificate may be usable for ECDH and/or * ECDSA cipher suites depending on the key usage extension. */ if (have_ecc_cert) { /* This call populates extension flags (ex_flags) */ x = (c->pkeys[SSL_PKEY_ECC]).x509; X509_check_purpose(x, -1, 0); ecdh_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_KEY_AGREEMENT) : 1; ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; 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);#ifndef OPENSSL_NO_ECDH if (ecdh_ok) { if ((signature_nid == NID_md5WithRSAEncryption) || (signature_nid == NID_md4WithRSAEncryption) || (signature_nid == NID_md2WithRSAEncryption)) { mask|=SSL_kECDH|SSL_aRSA; if (ecc_pkey_size <= 163) emask|=SSL_kECDH|SSL_aRSA; } if (signature_nid == NID_ecdsa_with_SHA1) { mask|=SSL_kECDH|SSL_aECDSA; if (ecc_pkey_size <= 163) emask|=SSL_kECDH|SSL_aECDSA; } }#endif#ifndef OPENSSL_NO_ECDSA if (ecdsa_ok) { mask|=SSL_aECDSA; emask|=SSL_aECDSA; }#endif }#ifndef OPENSSL_NO_ECDH if (have_ecdh_tmp) { mask|=SSL_kECDHE; emask|=SSL_kECDHE; }#endif c->mask=mask; c->export_mask=emask; c->valid=1; }/* This handy macro borrowed from crypto/x509v3/v3_purp.c */#define ku_reject(x, usage) \ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs) { unsigned long alg = cs->algorithms; EVP_PKEY *pkey = NULL; int keysize = 0; int signature_nid = 0; if (SSL_C_IS_EXPORT(cs)) { /* ECDH key length in export ciphers must be <= 163 bits */ pkey = X509_get_pubkey(x); if (pkey == NULL) return 0; keysize = EVP_PKEY_bits(pkey); EVP_PKEY_free(pkey); if (keysize > 163) return 0; } /* 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); if (alg & SSL_kECDH) { /* key usage, if present, must allow key agreement */ if (ku_reject(x, X509v3_KU_KEY_AGREEMENT)) { return 0; } if (alg & SSL_aECDSA) { /* signature alg must be ECDSA */ if (signature_nid != NID_ecdsa_with_SHA1) { return 0; } } if (alg & SSL_aRSA) { /* signature alg must be RSA */ if ((signature_nid != NID_md5WithRSAEncryption) && (signature_nid != NID_md4WithRSAEncryption) && (signature_nid != NID_md2WithRSAEncryption)) { return 0; } } } else if (alg & SSL_aECDSA) { /* key usage, if present, must allow signing */ if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) { return 0; } } return 1; /* all checks are ok */ }/* THIS NEEDS CLEANING UP */X509 *ssl_get_server_send_cert(SSL *s) { unsigned long alg,mask,kalg; CERT *c; int i,is_export; c=s->cert; ssl_set_cert_masks(c, s->s3->tmp.new_cipher); alg=s->s3->tmp.new_cipher->algorithms; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); mask=is_export?c->export_mask:c->mask; kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK); if (kalg & SSL_kECDH) { /* we don't need to look at SSL_kECDHE * since no certificate is needed for * anon ECDH and for authenticated * ECDHE, the check for the auth * algorithm will set i correctly * NOTE: For ECDH-RSA, we need an ECC * not an RSA cert but for ECDHE-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 (kalg & SSL_aECDSA) { i=SSL_PKEY_ECC; } else if (kalg & SSL_kDHr) i=SSL_PKEY_DH_RSA; else if (kalg & SSL_kDHd) i=SSL_PKEY_DH_DSA; else if (kalg & SSL_aDSS) i=SSL_PKEY_DSA_SIGN; else if (kalg & SSL_aRSA) { if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL) i=SSL_PKEY_RSA_SIGN; else i=SSL_PKEY_RSA_ENC; } else if (kalg & SSL_aKRB5) { /* VRS something else here? */ return(NULL); } else /* if (kalg & 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); }EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher) { unsigned long alg; CERT *c; alg=cipher->algorithms; c=s->cert; if ((alg & SSL_aDSS) && (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL)) return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey); else if (alg & SSL_aRSA) { 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); } else if ((alg & SSL_aECDSA) && (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) return(c->pkeys[SSL_PKEY_ECC].privatekey); else /* if (alg & SSL_aNULL) */ { SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); return(NULL); } }void ssl_update_cache(SSL *s,int mode) { int i; /* If the session_id_length is 0, we are not supposed to cache it, * and it would be rather hard to do anyway :-) */ if (s->session->session_id_length == 0) return; i=s->ctx->session_cache_mode; if ((i & mode) && (!s->hit) && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) || SSL_CTX_add_session(s->ctx,s->session)) && (s->ctx->new_session_cb != NULL)) { CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); if (!s->ctx->new_session_cb(s,s->session)) SSL_SESSION_free(s->session); } /* auto flush every 255 connections */ if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { if ( (((mode & SSL_SESS_CACHE_CLIENT) ?s->ctx->stats.sess_connect_good :s->ctx->stats.sess_accept_good) & 0xff) == 0xff) { SSL_CTX_flush_sessions(s->ctx,(unsigned long)time(NULL)); } } }SSL_METHOD *SSL_get_ssl_method(SSL *s) { return(s->method); }int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth) { int conn= -1; int ret=1; if (s->method != meth) { if (s->handshake_func != NULL) conn=(s->handshake_func == s->method->ssl_connect); if (s->method->version == meth->version) s->method=meth; else { s->method->ssl_free(s); s->method=meth; ret=s->method->ssl_new(s); } if (conn == 1) s->handshake_func=meth->ssl_connect; else if (conn == 0) s->handshake_func=meth->ssl_accept; } return(ret); }int SSL_get_error(const SSL *s,int i) { int reason; unsigned long l; BIO *bio; if (i > 0) return(SSL_ERROR_NONE); /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake * etc, where we do encode the error */ if ((l=ERR_peek_error()) != 0) { if (ERR_GET_LIB(l) == ERR_LIB_SYS) return(SSL_ERROR_SYSCALL); else return(SSL_ERROR_SSL); } if ((i < 0) && SSL_want_read(s)) { bio=SSL_get_rbio(s); if (BIO_should_read(bio)) return(SSL_ERROR_WANT_READ); else if (BIO_should_write(bio)) /* This one doesn't make too much sense ... We never try * to write to the rbio, and an application program where * rbio and wbio are separate couldn't even know what it * should wait for. * However if we ever set s->rwstate incorrectly * (so that we have SSL_want_read(s) instead of * SSL_want_write(s)) and rbio and wbio *are* the same, * this test works around that bug; so it might be safer * to keep it. */ return(SSL_ERROR_WANT_WRITE); else if (BIO_should_io_special(bio)) { reason=BIO_get_retry_reason(bio); if (reason == BIO_RR_CONNECT) return(SSL_ERROR_WANT_CONNECT); else if (reason == BIO_RR_ACCEPT) return(SSL_ERROR_WANT_ACCEPT); else return(SSL_ERROR_SYSCALL); /* unknown */ } } if ((i < 0) && SSL_want_write(s)) { bio=SSL_get_wbio(s); if (BIO_should_write(bio)) return(SSL_ERROR_WANT_WRITE); else if (BIO_should_read(bio)) /* See above (SSL_want_read(s) with BIO_should_write(bio)) */ return(SSL_ERROR_WANT_READ); else if (BIO_should_io_special(bio)) { reason=BIO_get_retry_reason(bio); if (reason == BIO_RR_CONNECT) return(SSL_ERROR_WANT_CONNECT); else if (reason == BIO_RR_ACCEPT) return(SSL_ERROR_WANT_ACCEPT); else return(SSL_ERROR_SYSCALL); } } if ((i < 0) && SSL_want_x509_lookup(s)) { return(SSL_ERROR_WANT_X509_LOOKUP); } if (i == 0) { if (s->version == SSL2_VERSION) { /* assume it is the socket being closed */ 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); }int SSL_do_handshake(SSL *s) { int ret=1; if (s->handshake_func == NULL) { SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_CONNECTION_TYPE_NOT_SET); return(-1); } s->method->ssl_renegotiate_check(s); if (SSL_in_init(s) || SSL_in_before(s)) { ret=s->handshake_func(s); } return(ret); }/* For the next 2 functions, SSL_clear() sets shutdown and so * one of these calls will reset it */void SSL_set_accept_state(SSL *s) { s->server=1; s->shutdown=0; s->state=SSL_ST_ACCEPT|SSL_ST_BEFORE; s->handshake_func=s->method->ssl_accept; /* clear the current cipher */ ssl_clear_cipher_ctx(s); }void SSL_set_connect_state(SSL *s) { s->server=0; s->shutdown=0; s->state=SSL_ST_CONNECT|SSL_ST_BEFORE; s->handshake_func=s->method->ssl_connect; /* clear the current cipher */ ssl_clear_cipher_ctx(s); }int ssl_undefined_function(SSL *s) { SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return(0); }int ssl_undefined_void_function(void) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -