📄 s3_clnt.c
字号:
else { /* we get them from the cert */ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); goto err; } /* generate a new random key */ if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } if (!DH_generate_key(dh_clnt)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } /* use the 'p' output buffer for the DH key, but * make sure to clear it out afterwards */ n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt); if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); goto err; } /* generate master key from the result */ s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,n); /* clean up */ memset(p,0,n); /* send off the data */ n=BN_num_bytes(dh_clnt->pub_key); s2n(n,p); BN_bn2bin(dh_clnt->pub_key,p); n+=2; DH_free(dh_clnt); /* perhaps clean things up a bit EAY EAY EAY EAY*/ }#endif#ifndef OPENSSL_NO_ECDH else if ((l & SSL_kECDH) || (l & SSL_kECDHE)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; int ecdh_clnt_cert = 0; int field_size = 0; /* Did we send out the client's * ECDH share for use in premaster * computation as part of client certificate? * If so, set ecdh_clnt_cert to 1. */ if ((l & SSL_kECDH) && (s->cert != NULL)) { /* XXX: For now, we do not support client * authentication using ECDH certificates. * To add such support, one needs to add * code that checks for appropriate * conditions and sets ecdh_clnt_cert to 1. * For example, the cert have an ECC * key on the same curve as the server's * and the key should be authorized for * key agreement. * * One also needs to add code in ssl3_connect * to skip sending the certificate verify * message. * * if ((s->cert->key->privatekey != NULL) && * (s->cert->key->privatekey->type == * EVP_PKEY_EC) && ...) * ecdh_clnt_cert = 1; */ } if (s->session->sess_cert->peer_ecdh_tmp != NULL) { tkey = s->session->sess_cert->peer_ecdh_tmp; } else { /* Get the Server Public Key from Cert */ srvr_pub_pkey = X509_get_pubkey(s->session-> \ sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); if ((srvr_pub_pkey == NULL) || (srvr_pub_pkey->type != EVP_PKEY_EC) || (srvr_pub_pkey->pkey.ec == NULL)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } tkey = srvr_pub_pkey->pkey.ec; } srvr_group = EC_KEY_get0_group(tkey); srvr_ecpoint = EC_KEY_get0_public_key(tkey); if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } if ((clnt_ecdh=EC_KEY_new()) == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); goto err; } if (ecdh_clnt_cert) { /* Reuse key info from our certificate * We only need our private key to perform * the ECDH computation. */ const BIGNUM *priv_key; tkey = s->cert->key->privatekey->pkey.ec; priv_key = EC_KEY_get0_private_key(tkey); if (priv_key == NULL) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); goto err; } } else { /* Generate a new ECDH key pair */ if (!(EC_KEY_generate_key(clnt_ecdh))) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } } /* use the 'p' output buffer for the ECDH key, but * make sure to clear it out afterwards */ field_size = EC_GROUP_get_degree(srvr_group); if (field_size <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } /* If field size is not more than 24 octets, then use SHA-1 hash of result; * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt; * this is new with this version of the Internet Draft). */ if (field_size <= 24 * 8) n=ECDH_compute_key(p, KDF1_SHA1_len, srvr_ecpoint, clnt_ecdh, KDF1_SHA1); else n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } /* generate master key from the result */ s->session->master_key_length = s->method->ssl3_enc \ -> generate_master_secret(s, s->session->master_key, p, n); memset(p, 0, n); /* clean up */ if (ecdh_clnt_cert) { /* Send empty client key exch message */ n = 0; } else { /* First check the size of encoding and * allocate memory accordingly. */ encoded_pt_len = EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh), POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); encodedPoint = (unsigned char *) OPENSSL_malloc(encoded_pt_len * sizeof(unsigned char)); bn_ctx = BN_CTX_new(); if ((encodedPoint == NULL) || (bn_ctx == NULL)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } /* Encode the public key */ n = EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh), POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, bn_ctx); *p = n; /* length of encoded point */ /* Encoded point will be copied here */ p += 1; /* copy the point */ memcpy((unsigned char *)p, encodedPoint, n); /* increment n to account for length field */ n += 1; } /* Free allocated memory */ BN_CTX_free(bn_ctx); if (encodedPoint != NULL) OPENSSL_free(encodedPoint); if (clnt_ecdh != NULL) EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); }#endif /* !OPENSSL_NO_ECDH */ else { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; l2n3(n,d); s->state=SSL3_ST_CW_KEY_EXCH_B; /* number of bytes to write */ s->init_num=n+4; s->init_off=0; } /* SSL3_ST_CW_KEY_EXCH_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));err:#ifndef OPENSSL_NO_ECDH BN_CTX_free(bn_ctx); if (encodedPoint != NULL) OPENSSL_free(encodedPoint); if (clnt_ecdh != NULL) EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey);#endif return(-1); }int ssl3_send_client_verify(SSL *s) { unsigned char *p,*d; unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; EVP_PKEY *pkey;#ifndef OPENSSL_NO_RSA unsigned u=0;#endif unsigned long n;#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) int j;#endif if (s->state == SSL3_ST_CW_CERT_VRFY_A) { d=(unsigned char *)s->init_buf->data; p= &(d[4]); pkey=s->cert->key->privatekey; s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2), &(data[MD5_DIGEST_LENGTH]));#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst1),&(data[0])); if (RSA_sign(NID_md5_sha1, data, MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, &(p[2]), &u, pkey->pkey.rsa) <= 0 ) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); goto err; } s2n(u,p); n=u+2; } else#endif#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { if (!DSA_sign(pkey->save_type, &(data[MD5_DIGEST_LENGTH]), SHA_DIGEST_LENGTH,&(p[2]), (unsigned int *)&j,pkey->pkey.dsa)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB); goto err; } s2n(j,p); n=j+2; } else#endif#ifndef OPENSSL_NO_ECDSA if (pkey->type == EVP_PKEY_EC) { if (!ECDSA_sign(pkey->save_type, &(data[MD5_DIGEST_LENGTH]), SHA_DIGEST_LENGTH,&(p[2]), (unsigned int *)&j,pkey->pkey.ec)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_ECDSA_LIB); goto err; } s2n(j,p); n=j+2; } else#endif { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); goto err; } *(d++)=SSL3_MT_CERTIFICATE_VERIFY; l2n3(n,d); s->state=SSL3_ST_CW_CERT_VRFY_B; s->init_num=(int)n+4; s->init_off=0; } return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));err: return(-1); }int ssl3_send_client_certificate(SSL *s) { X509 *x509=NULL; EVP_PKEY *pkey=NULL; int i; unsigned long l; if (s->state == SSL3_ST_CW_CERT_A) { if ((s->cert == NULL) || (s->cert->key->x509 == NULL) || (s->cert->key->privatekey == NULL)) s->state=SSL3_ST_CW_CERT_B; else s->state=SSL3_ST_CW_CERT_C; } /* We need to get a client cert */ if (s->state == SSL3_ST_CW_CERT_B) { /* If we get an error, we need to * ssl->rwstate=SSL_X509_LOOKUP; return(-1); * We then get retied later */ i=0; if (s->ctx->client_cert_cb != NULL) i=s->ctx->client_cert_cb(s,&(x509),&(pkey)); if (i < 0) { s->rwstate=SSL_X509_LOOKUP; return(-1); } s->rwstate=SSL_NOTHING; if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { s->state=SSL3_ST_CW_CERT_B; if ( !SSL_use_certificate(s,x509) || !SSL_use_PrivateKey(s,pkey)) i=0; } else if (i == 1) { i=0; SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); } if (x509 != NULL) X509_free(x509); if (pkey != NULL) EVP_PKEY_free(pkey); if (i == 0) { if (s->version == SSL3_VERSION) { s->s3->tmp.cert_req=0; ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE); return(1); } else { s->s3->tmp.cert_req=2; } } /* Ok, we have a cert */ s->state=SSL3_ST_CW_CERT_C; } if (s->state == SSL3_ST_CW_CERT_C) { s->state=SSL3_ST_CW_CERT_D; l=ssl3_output_cert_chain(s, (s->s3->tmp.cert_req == 2)?NULL:s->cert->key->x509); s->init_num=(int)l; s->init_off=0; } /* SSL3_ST_CW_CERT_D */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); }#define has_bits(i,m) (((i)&(m)) == (m))int ssl3_check_cert_and_algorithm(SSL *s) { int i,idx; long algs; EVP_PKEY *pkey=NULL; SESS_CERT *sc;#ifndef OPENSSL_NO_RSA RSA *rsa;#endif#ifndef OPENSSL_NO_DH DH *dh;#endif sc=s->session->sess_cert; if (sc == NULL) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR); goto err; } algs=s->s3->tmp.new_cipher->algorithms; /* we don't have a certificate */ if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) return(1);#ifndef OPENSSL_NO_RSA rsa=s->session->sess_cert->peer_rsa_tmp;#endif#ifndef OPENSSL_NO_DH dh=s->session->sess_cert->peer_dh_tmp;#endif /* This is the passed certificate */ idx=sc->peer_cert_type;#ifndef OPENSSL_NO_ECDH if (idx == SSL_PKEY_ECC) { if (check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s->s3->tmp.new_cipher) == 0) { /* check failed */ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT); goto f_err; } else { return 1; } }#endif pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); EVP_PKEY_free(pkey); /* Check that we have a certificate if we require one */ if ((algs & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT); goto f_err; }#ifndef OPENSSL_NO_DSA else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT); goto f_err; }#endif#ifndef OPENSSL_NO_RSA if ((algs & SSL_kRSA) && !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); goto f_err; }#endif#ifndef OPENSSL_NO_DH if ((algs & SSL_kEDH) && !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); goto f_err; } else if ((algs & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); goto f_err; }#ifndef OPENSSL_NO_DSA else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); goto f_err; }#endif#endif if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) {#ifndef OPENSSL_NO_RSA if (algs & SSL_kRSA) { if (rsa == NULL || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); goto f_err; } } else#endif#ifndef OPENSSL_NO_DH if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { if (dh == NULL || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY); goto f_err; } } else#endif { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } } return(1);f_err: ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);err: return(0); }#ifndef OPENSSL_NO_ECDH/* This is the complement of nid2curve_id in s3_srvr.c. */static int curve_id2nid(int curve_id){ /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */ static int nid_list[26] = { 0, NID_sect163k1, /* sect163k1 (1) */ NID_sect163r1, /* sect163r1 (2) */ NID_sect163r2, /* sect163r2 (3) */ NID_sect193r1, /* sect193r1 (4) */ NID_sect193r2, /* sect193r2 (5) */ NID_sect233k1, /* sect233k1 (6) */ NID_sect233r1, /* sect233r1 (7) */ NID_sect239k1, /* sect239k1 (8) */ NID_sect283k1, /* sect283k1 (9) */ NID_sect283r1, /* sect283r1 (10) */ NID_sect409k1, /* sect409k1 (11) */ NID_sect409r1, /* sect409r1 (12) */ NID_sect571k1, /* sect571k1 (13) */ NID_sect571r1, /* sect571r1 (14) */ NID_secp160k1, /* secp160k1 (15) */ NID_secp160r1, /* secp160r1 (16) */ NID_secp160r2, /* secp160r2 (17) */ NID_secp192k1, /* secp192k1 (18) */ NID_X9_62_prime192v1, /* secp192r1 (19) */ NID_secp224k1, /* secp224k1 (20) */ NID_secp224r1, /* secp224r1 (21) */ NID_secp256k1, /* secp256k1 (22) */ NID_X9_62_prime256v1, /* secp256r1 (23) */ NID_secp384r1, /* secp384r1 (24) */ NID_secp521r1 /* secp521r1 (25) */ }; if ((curve_id < 1) || (curve_id > 25)) return 0; return nid_list[curve_id];}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -