📄 s3_srvr.c
字号:
if (s->state == SSL3_ST_SW_CERT_REQ_A) { buf=s->init_buf; d=p=(unsigned char *)&(buf->data[4]); /* get the list of acceptable cert types */ p++; n=ssl3_get_req_cert_type(s,p); d[0]=n; p+=n; n++; off=n; p+=2; n+=2; sk=SSL_get_client_CA_list(s); nl=0; if (sk != NULL) { for (i=0; i<sk_X509_NAME_num(sk); i++) { name=sk_X509_NAME_value(sk,i); j=i2d_X509_NAME(name,NULL); if (!BUF_MEM_grow_clean(buf,4+n+j+2)) { SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); goto err; } p=(unsigned char *)&(buf->data[4+n]); if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) { s2n(j,p); i2d_X509_NAME(name,&p); n+=2+j; nl+=2+j; } else { d=p; i2d_X509_NAME(name,&p); j-=2; s2n(j,d); j+=2; n+=j; nl+=j; } } } /* else no CA names */ p=(unsigned char *)&(buf->data[4+off]); s2n(nl,p); d=(unsigned char *)buf->data; *(d++)=SSL3_MT_CERTIFICATE_REQUEST; l2n3(n,d); /* we should now have things packed up, so lets send * it off */ s->init_num=n+4; s->init_off=0;#ifdef NETSCAPE_HANG_BUG p=(unsigned char *)s->init_buf->data + s->init_num; /* do the header */ *(p++)=SSL3_MT_SERVER_DONE; *(p++)=0; *(p++)=0; *(p++)=0; s->init_num += 4;#endif s->state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));err: return(-1); }#ifndef OPENSSL_NO_ECDHstatic const int KDF1_SHA1_len = 20;static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) {#ifndef OPENSSL_NO_SHA if (*outlen < SHA_DIGEST_LENGTH) return NULL; else *outlen = SHA_DIGEST_LENGTH; return SHA1(in, inlen, out);#else return NULL;#endif /* OPENSSL_NO_SHA */ }#endif /* OPENSSL_NO_ECDH */int ssl3_get_client_key_exchange(SSL *s) { int i,al,ok; long n; unsigned long l; unsigned char *p;#ifndef OPENSSL_NO_RSA RSA *rsa=NULL; EVP_PKEY *pkey=NULL;#endif#ifndef OPENSSL_NO_DH BIGNUM *pub=NULL; DH *dh_srvr;#endif#ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err;#endif /* OPENSSL_NO_KRB5 */#ifndef OPENSSL_NO_ECDH EC_KEY *srvr_ecdh = NULL; EVP_PKEY *clnt_pub_pkey = NULL; EC_POINT *clnt_ecpoint = NULL; BN_CTX *bn_ctx = NULL; #endif n=s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, /* ??? */ &ok); if (!ok) return((int)n); p=(unsigned char *)s->init_msg; l=s->s3->tmp.new_cipher->algorithms;#ifndef OPENSSL_NO_RSA if (l & SSL_kRSA) { /* FIX THIS UP EAY EAY EAY EAY */ if (s->s3->tmp.use_rsa_tmp) { if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) rsa=s->cert->rsa_tmp; /* Don't do a callback because rsa_tmp should * be sent already */ if (rsa == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_PKEY); goto f_err; } } else { pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; if ( (pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE); goto f_err; } rsa=pkey->pkey.rsa; } /* TLS */ if (s->version > SSL3_VERSION) { n2s(p,i); if (n != i+2) { if (!(s->options & SSL_OP_TLS_D5_BUG)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); goto err; } else p-=2; } else n=i; } i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); al = -1; if (i != SSL_MAX_MASTER_KEY_LENGTH) { al=SSL_AD_DECODE_ERROR; /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */ } if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) { /* The premaster secret must contain the same version number as the * ClientHello to detect version rollback attacks (strangely, the * protocol does not offer such protection for DH ciphersuites). * However, buggy clients exist that send the negotiated protocol * version instead if the server does not support the requested * protocol version. * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) && (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff)))) { al=SSL_AD_DECODE_ERROR; /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */ /* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack * (http://eprint.iacr.org/2003/052/) exploits the version * number check as a "bad version oracle" -- an alert would * reveal that the plaintext corresponding to some ciphertext * made up by the adversary is properly formatted except * that the version number is wrong. To avoid such attacks, * we should treat this just like any other decryption error. */ } } if (al != -1) { /* Some decryption failure -- use random value instead as countermeasure * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding * (see RFC 2246, section 7.4.7.1). */ ERR_clear_error(); i = SSL_MAX_MASTER_KEY_LENGTH; p[0] = s->client_version >> 8; p[1] = s->client_version & 0xff; if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */ goto err; } s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, p,i); OPENSSL_cleanse(p,i); } else#endif#ifndef OPENSSL_NO_DH if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { n2s(p,i); if (n != i+2) { if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); goto err; } else { p-=2; i=(int)n; } } if (n == 0L) /* the parameters are in the cert */ { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS); goto f_err; } else { if (s->s3->tmp.dh == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } else dh_srvr=s->s3->tmp.dh; } pub=BN_bin2bn(p,i,NULL); if (pub == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB); goto err; } i=DH_compute_key(p,pub,dh_srvr); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } DH_free(s->s3->tmp.dh); s->s3->tmp.dh=NULL; BN_clear_free(pub); pub=NULL; s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,i); OPENSSL_cleanse(p,i); } else#endif#ifndef OPENSSL_NO_KRB5 if (l & SSL_kKRB5) { krb5_error_code krb5rc; krb5_data enc_ticket; krb5_data authenticator; krb5_data enc_pms; KSSL_CTX *kssl_ctx = s->kssl_ctx; EVP_CIPHER_CTX ciph_ctx; EVP_CIPHER *enc = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH + EVP_MAX_BLOCK_LENGTH]; int padl, outl; krb5_timestamp authtime = 0; krb5_ticket_times ttimes; EVP_CIPHER_CTX_init(&ciph_ctx); if (!kssl_ctx) kssl_ctx = kssl_ctx_new(); n2s(p,i); enc_ticket.length = i; if (n < (int)enc_ticket.length + 6) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } enc_ticket.data = (char *)p; p+=enc_ticket.length; n2s(p,i); authenticator.length = i; if (n < (int)(enc_ticket.length + authenticator.length) + 6) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } authenticator.data = (char *)p; p+=authenticator.length; n2s(p,i); enc_pms.length = i; enc_pms.data = (char *)p; p+=enc_pms.length; /* Note that the length is checked again below, ** after decryption */ if(enc_pms.length > sizeof pms) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } if (n != (long)(enc_ticket.length + authenticator.length + enc_pms.length + 6)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes, &kssl_err)) != 0) {#ifdef KSSL_DEBUG printf("kssl_sget_tkt rtn %d [%d]\n", krb5rc, kssl_err.reason); if (kssl_err.text) printf("kssl_err text= %s\n", kssl_err.text);#endif /* KSSL_DEBUG */ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, kssl_err.reason); goto err; } /* Note: no authenticator is not considered an error, ** but will return authtime == 0. */ if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator, &authtime, &kssl_err)) != 0) {#ifdef KSSL_DEBUG printf("kssl_check_authent rtn %d [%d]\n", krb5rc, kssl_err.reason); if (kssl_err.text) printf("kssl_err text= %s\n", kssl_err.text);#endif /* KSSL_DEBUG */ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, kssl_err.reason); goto err; } if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc); goto err; }#ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx);#endif /* KSSL_DEBUG */ enc = kssl_map_enc(kssl_ctx->enctype); if (enc == NULL) goto err; memset(iv, 0, sizeof iv); /* per RFC 1510 */ if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); goto err; } if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl, (unsigned char *)enc_pms.data, enc_pms.length)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); goto err; } if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); goto err; } outl += padl; if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); goto err; } EVP_CIPHER_CTX_cleanup(&ciph_ctx); s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, pms, outl); if (kssl_ctx->client_princ) { int len = strlen(kssl_ctx->client_princ); if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) { s->session->krb5_client_princ_len = len; memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len); } } /* Was doing kssl_ctx_free() here, ** but it caused problems for apache. ** kssl_ctx = kssl_ctx_free(kssl_ctx); ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ } else#endif /* OPENSSL_NO_KRB5 */#ifndef OPENSSL_NO_ECDH if ((l & SSL_kECDH) || (l & SSL_kECDHE)) { int ret = 1; int field_size = 0; const EC_KEY *tkey; const EC_GROUP *group; const BIGNUM *priv_key; /* initialize structures for server's ECDH key pair */ if ((srvr_ecdh = EC_KEY_new()) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto err; } /* Let's get server private key and group information */ if (l & SSL_kECDH) { /* use the certificate */ tkey = s->cert->key->privatekey->pkey.ec; } else { /* use the ephermeral values we saved when * generating the ServerKeyExchange msg. */ tkey = s->s3->tmp.ecdh; } group = EC_KEY_get0_group(tkey); priv_key = EC_KEY_get0_private_key(tkey); if (!EC_KEY_set_group(srvr_ecdh, group) || !EC_KEY_set_private_key(srvr_ecdh, priv_key)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -