Loading ssl/d1_clnt.c +304 −3 Original line number Diff line number Diff line Loading @@ -284,8 +284,9 @@ int dtls1_connect(SSL *s) case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: /* Check if it is anon DH */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) /* Check if it is anon DH or PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret=ssl3_get_server_certificate(s); if (ret <= 0) goto end; Loading Loading @@ -716,6 +717,14 @@ int dtls1_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err; #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_ECDH EC_KEY *clnt_ecdh = NULL; const EC_POINT *srvr_ecpoint = NULL; EVP_PKEY *srvr_pub_pkey = NULL; unsigned char *encodedPoint = NULL; int encoded_pt_len = 0; BN_CTX * bn_ctx = NULL; #endif if (s->state == SSL3_ST_CW_KEY_EXCH_A) { Loading Loading @@ -972,6 +981,274 @@ int dtls1_send_client_key_exchange(SSL *s) /* perhaps clean things up a bit EAY EAY EAY EAY*/ } #endif #ifndef OPENSSL_NO_ECDH else if (alg_k & (SSL_kEECDH|SSL_kECDHr|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 ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (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_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } if ((clnt_ecdh=EC_KEY_new()) == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { SSLerr(SSL_F_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) { SSLerr(SSL_F_DTLS1_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_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); if (n <= 0) { SSLerr(SSL_F_DTLS1_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_DTLS1_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 */ #ifndef OPENSSL_NO_PSK else if (alg_k & SSL_kPSK) { char identity[PSK_MAX_IDENTITY_LEN]; unsigned char *t = NULL; unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; unsigned int pre_ms_len = 0, psk_len = 0; int psk_err = 1; n = 0; if (s->psk_client_callback == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, SSL_R_PSK_NO_CLIENT_CB); goto err; } psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, identity, PSK_MAX_IDENTITY_LEN, psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_len > PSK_MAX_PSK_LEN) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto psk_err; } else if (psk_len == 0) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } /* create PSK pre_master_secret */ pre_ms_len = 2+psk_len+2+psk_len; t = psk_or_pre_ms; memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); s2n(psk_len, t); memset(t, 0, psk_len); t+=psk_len; s2n(psk_len, t); if (s->session->psk_identity_hint != NULL) OPENSSL_free(s->session->psk_identity_hint); s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); if (s->ctx->psk_identity_hint != NULL && s->session->psk_identity_hint == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto psk_err; } if (s->session->psk_identity != NULL) OPENSSL_free(s->session->psk_identity); s->session->psk_identity = BUF_strdup(identity); if (s->session->psk_identity == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto psk_err; } s->session->master_key_length = s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, psk_or_pre_ms, pre_ms_len); n = strlen(identity); s2n(n, p); memcpy(p, identity, n); n+=2; psk_err = 0; psk_err: OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_err != 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; } } #endif else { Loading Loading @@ -1001,6 +1278,13 @@ int dtls1_send_client_key_exchange(SSL *s) /* SSL3_ST_CW_KEY_EXCH_B */ return(dtls1_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); } Loading @@ -1013,7 +1297,7 @@ int dtls1_send_client_verify(SSL *s) unsigned u=0; #endif unsigned long n; #ifndef OPENSSL_NO_DSA #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) int j; #endif Loading Loading @@ -1060,6 +1344,23 @@ int dtls1_send_client_verify(SSL *s) 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_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); Loading ssl/d1_lib.c +0 −3 Original line number Diff line number Diff line Loading @@ -203,9 +203,6 @@ const SSL_CIPHER *dtls1_get_cipher(unsigned int u) { if (ciph->algorithm_enc == SSL_RC4) return NULL; /* We currently don't support ECDH either */ if (ciph->algorithm_mkey & SSL_kEECDH) return NULL; } return ciph; Loading ssl/d1_srvr.c +239 −12 Original line number Diff line number Diff line Loading @@ -311,8 +311,9 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=dtls1_send_server_certificate(s); Loading Loading @@ -346,7 +347,13 @@ int dtls1_accept(SSL *s) /* only send if a DH key exchange or * RSA but we have a sign only certificate */ if (s->s3->tmp.use_rsa_tmp /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) Loading Loading @@ -383,7 +390,10 @@ int dtls1_accept(SSL *s) * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; Loading Loading @@ -458,6 +468,21 @@ int dtls1_accept(SSL *s) s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state=SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, Loading @@ -466,7 +491,7 @@ int dtls1_accept(SSL *s) s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: Loading Loading @@ -788,6 +813,13 @@ int dtls1_send_server_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_DH DH *dh=NULL,*dhp; #endif #ifndef OPENSSL_NO_ECDH EC_KEY *ecdh=NULL, *ecdhp; unsigned char *encodedPoint = NULL; int encodedlen = 0; int curve_id = 0; BN_CTX *bn_ctx = NULL; #endif EVP_PKEY *pkey; unsigned char *p,*d; Loading Loading @@ -897,6 +929,142 @@ int dtls1_send_server_key_exchange(SSL *s) } else #endif #ifndef OPENSSL_NO_ECDH if (type & SSL_kEECDH) { const EC_GROUP *group; ecdhp=cert->ecdh_tmp; if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) { ecdhp=s->cert->ecdh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); } if (ecdhp == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); goto f_err; } if (s->s3->tmp.ecdh != NULL) { EC_KEY_free(s->s3->tmp.ecdh); SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } /* Duplicate the ECDH structure. */ if (ecdhp == NULL) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } if (!EC_KEY_up_ref(ecdhp)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } ecdh = ecdhp; s->s3->tmp.ecdh=ecdh; if ((EC_KEY_get0_public_key(ecdh) == NULL) || (EC_KEY_get0_private_key(ecdh) == NULL) || (s->options & SSL_OP_SINGLE_ECDH_USE)) { if(!EC_KEY_generate_key(ecdh)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } } if (((group = EC_KEY_get0_group(ecdh)) == NULL) || (EC_KEY_get0_public_key(ecdh) == NULL) || (EC_KEY_get0_private_key(ecdh) == NULL)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && (EC_GROUP_get_degree(group) > 163)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); goto err; } /* XXX: For now, we only support ephemeral ECDH * keys over named (not generic) curves. For * supported named curves, curve_id is non-zero. */ if ((curve_id = tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) == 0) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); goto err; } /* Encode the public key. * First check the size of encoding and * allocate memory accordingly. */ encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); encodedPoint = (unsigned char *) OPENSSL_malloc(encodedlen*sizeof(unsigned char)); bn_ctx = BN_CTX_new(); if ((encodedPoint == NULL) || (bn_ctx == NULL)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encodedlen, bn_ctx); if (encodedlen == 0) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } BN_CTX_free(bn_ctx); bn_ctx=NULL; /* XXX: For now, we only support named (not * generic) curves in ECDH ephemeral key exchanges. * In this situation, we need four additional bytes * to encode the entire ServerECDHParams * structure. */ n = 4 + encodedlen; /* We'll generate the serverKeyExchange message * explicitly so we can set these to NULLs */ r[0]=NULL; r[1]=NULL; r[2]=NULL; r[3]=NULL; } else #endif /* !OPENSSL_NO_ECDH */ #ifndef OPENSSL_NO_PSK if (type & SSL_kPSK) { /* reserve size for record length and PSK identity hint*/ n+=2+strlen(s->ctx->psk_identity_hint); } else #endif /* !OPENSSL_NO_PSK */ { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); Loading @@ -908,7 +1076,8 @@ int dtls1_send_server_key_exchange(SSL *s) n+=2+nr[i]; } if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) == NULL) Loading Loading @@ -939,6 +1108,41 @@ int dtls1_send_server_key_exchange(SSL *s) p+=nr[i]; } #ifndef OPENSSL_NO_ECDH if (type & SSL_kEECDH) { /* XXX: For now, we only support named (not generic) curves. * In this situation, the serverKeyExchange message has: * [1 byte CurveType], [2 byte CurveName] * [1 byte length of encoded point], followed by * the actual encoded point itself */ *p = NAMED_CURVE_TYPE; p += 1; *p = 0; p += 1; *p = curve_id; p += 1; *p = encodedlen; p += 1; memcpy((unsigned char*)p, (unsigned char *)encodedPoint, encodedlen); OPENSSL_free(encodedPoint); p += encodedlen; } #endif #ifndef OPENSSL_NO_PSK if (type & SSL_kPSK) { /* copy PSK identity hint */ s2n(strlen(s->ctx->psk_identity_hint), p); strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); p+=strlen(s->ctx->psk_identity_hint); } #endif /* not anonymous */ if (pkey != NULL) { Loading Loading @@ -991,6 +1195,25 @@ int dtls1_send_server_key_exchange(SSL *s) n+=i+2; } else #endif #if !defined(OPENSSL_NO_ECDSA) if (pkey->type == EVP_PKEY_EC) { /* let's do ECDSA */ EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(d[4]),n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA); goto err; } s2n(i,p); n+=i+2; } else #endif { /* Is this error check actually needed? */ Loading Loading @@ -1018,6 +1241,10 @@ int dtls1_send_server_key_exchange(SSL *s) f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: #ifndef OPENSSL_NO_ECDH if (encodedPoint != NULL) OPENSSL_free(encodedPoint); BN_CTX_free(bn_ctx); #endif EVP_MD_CTX_cleanup(&md_ctx); return(-1); } Loading Loading
ssl/d1_clnt.c +304 −3 Original line number Diff line number Diff line Loading @@ -284,8 +284,9 @@ int dtls1_connect(SSL *s) case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: /* Check if it is anon DH */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) /* Check if it is anon DH or PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret=ssl3_get_server_certificate(s); if (ret <= 0) goto end; Loading Loading @@ -716,6 +717,14 @@ int dtls1_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err; #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_ECDH EC_KEY *clnt_ecdh = NULL; const EC_POINT *srvr_ecpoint = NULL; EVP_PKEY *srvr_pub_pkey = NULL; unsigned char *encodedPoint = NULL; int encoded_pt_len = 0; BN_CTX * bn_ctx = NULL; #endif if (s->state == SSL3_ST_CW_KEY_EXCH_A) { Loading Loading @@ -972,6 +981,274 @@ int dtls1_send_client_key_exchange(SSL *s) /* perhaps clean things up a bit EAY EAY EAY EAY*/ } #endif #ifndef OPENSSL_NO_ECDH else if (alg_k & (SSL_kEECDH|SSL_kECDHr|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 ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (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_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } if ((clnt_ecdh=EC_KEY_new()) == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { SSLerr(SSL_F_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) { SSLerr(SSL_F_DTLS1_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_DTLS1_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_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); if (n <= 0) { SSLerr(SSL_F_DTLS1_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_DTLS1_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 */ #ifndef OPENSSL_NO_PSK else if (alg_k & SSL_kPSK) { char identity[PSK_MAX_IDENTITY_LEN]; unsigned char *t = NULL; unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; unsigned int pre_ms_len = 0, psk_len = 0; int psk_err = 1; n = 0; if (s->psk_client_callback == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, SSL_R_PSK_NO_CLIENT_CB); goto err; } psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, identity, PSK_MAX_IDENTITY_LEN, psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_len > PSK_MAX_PSK_LEN) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto psk_err; } else if (psk_len == 0) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } /* create PSK pre_master_secret */ pre_ms_len = 2+psk_len+2+psk_len; t = psk_or_pre_ms; memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); s2n(psk_len, t); memset(t, 0, psk_len); t+=psk_len; s2n(psk_len, t); if (s->session->psk_identity_hint != NULL) OPENSSL_free(s->session->psk_identity_hint); s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); if (s->ctx->psk_identity_hint != NULL && s->session->psk_identity_hint == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto psk_err; } if (s->session->psk_identity != NULL) OPENSSL_free(s->session->psk_identity); s->session->psk_identity = BUF_strdup(identity); if (s->session->psk_identity == NULL) { SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto psk_err; } s->session->master_key_length = s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, psk_or_pre_ms, pre_ms_len); n = strlen(identity); s2n(n, p); memcpy(p, identity, n); n+=2; psk_err = 0; psk_err: OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_err != 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; } } #endif else { Loading Loading @@ -1001,6 +1278,13 @@ int dtls1_send_client_key_exchange(SSL *s) /* SSL3_ST_CW_KEY_EXCH_B */ return(dtls1_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); } Loading @@ -1013,7 +1297,7 @@ int dtls1_send_client_verify(SSL *s) unsigned u=0; #endif unsigned long n; #ifndef OPENSSL_NO_DSA #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) int j; #endif Loading Loading @@ -1060,6 +1344,23 @@ int dtls1_send_client_verify(SSL *s) 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_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); Loading
ssl/d1_lib.c +0 −3 Original line number Diff line number Diff line Loading @@ -203,9 +203,6 @@ const SSL_CIPHER *dtls1_get_cipher(unsigned int u) { if (ciph->algorithm_enc == SSL_RC4) return NULL; /* We currently don't support ECDH either */ if (ciph->algorithm_mkey & SSL_kEECDH) return NULL; } return ciph; Loading
ssl/d1_srvr.c +239 −12 Original line number Diff line number Diff line Loading @@ -311,8 +311,9 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) /* Check if it is anon DH or normal PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); ret=dtls1_send_server_certificate(s); Loading Loading @@ -346,7 +347,13 @@ int dtls1_accept(SSL *s) /* only send if a DH key exchange or * RSA but we have a sign only certificate */ if (s->s3->tmp.use_rsa_tmp /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) Loading Loading @@ -383,7 +390,10 @@ int dtls1_accept(SSL *s) * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; Loading Loading @@ -458,6 +468,21 @@ int dtls1_accept(SSL *s) s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. */ s->state=SSL3_ST_SR_FINISHED_A; s->init_num = 0; } else { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, Loading @@ -466,7 +491,7 @@ int dtls1_accept(SSL *s) s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); } break; case SSL3_ST_SR_CERT_VRFY_A: Loading Loading @@ -788,6 +813,13 @@ int dtls1_send_server_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_DH DH *dh=NULL,*dhp; #endif #ifndef OPENSSL_NO_ECDH EC_KEY *ecdh=NULL, *ecdhp; unsigned char *encodedPoint = NULL; int encodedlen = 0; int curve_id = 0; BN_CTX *bn_ctx = NULL; #endif EVP_PKEY *pkey; unsigned char *p,*d; Loading Loading @@ -897,6 +929,142 @@ int dtls1_send_server_key_exchange(SSL *s) } else #endif #ifndef OPENSSL_NO_ECDH if (type & SSL_kEECDH) { const EC_GROUP *group; ecdhp=cert->ecdh_tmp; if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) { ecdhp=s->cert->ecdh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); } if (ecdhp == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); goto f_err; } if (s->s3->tmp.ecdh != NULL) { EC_KEY_free(s->s3->tmp.ecdh); SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } /* Duplicate the ECDH structure. */ if (ecdhp == NULL) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } if (!EC_KEY_up_ref(ecdhp)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } ecdh = ecdhp; s->s3->tmp.ecdh=ecdh; if ((EC_KEY_get0_public_key(ecdh) == NULL) || (EC_KEY_get0_private_key(ecdh) == NULL) || (s->options & SSL_OP_SINGLE_ECDH_USE)) { if(!EC_KEY_generate_key(ecdh)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } } if (((group = EC_KEY_get0_group(ecdh)) == NULL) || (EC_KEY_get0_public_key(ecdh) == NULL) || (EC_KEY_get0_private_key(ecdh) == NULL)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && (EC_GROUP_get_degree(group) > 163)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); goto err; } /* XXX: For now, we only support ephemeral ECDH * keys over named (not generic) curves. For * supported named curves, curve_id is non-zero. */ if ((curve_id = tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) == 0) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); goto err; } /* Encode the public key. * First check the size of encoding and * allocate memory accordingly. */ encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); encodedPoint = (unsigned char *) OPENSSL_malloc(encodedlen*sizeof(unsigned char)); bn_ctx = BN_CTX_new(); if ((encodedPoint == NULL) || (bn_ctx == NULL)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); goto err; } encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encodedlen, bn_ctx); if (encodedlen == 0) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } BN_CTX_free(bn_ctx); bn_ctx=NULL; /* XXX: For now, we only support named (not * generic) curves in ECDH ephemeral key exchanges. * In this situation, we need four additional bytes * to encode the entire ServerECDHParams * structure. */ n = 4 + encodedlen; /* We'll generate the serverKeyExchange message * explicitly so we can set these to NULLs */ r[0]=NULL; r[1]=NULL; r[2]=NULL; r[3]=NULL; } else #endif /* !OPENSSL_NO_ECDH */ #ifndef OPENSSL_NO_PSK if (type & SSL_kPSK) { /* reserve size for record length and PSK identity hint*/ n+=2+strlen(s->ctx->psk_identity_hint); } else #endif /* !OPENSSL_NO_PSK */ { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); Loading @@ -908,7 +1076,8 @@ int dtls1_send_server_key_exchange(SSL *s) n+=2+nr[i]; } if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) == NULL) Loading Loading @@ -939,6 +1108,41 @@ int dtls1_send_server_key_exchange(SSL *s) p+=nr[i]; } #ifndef OPENSSL_NO_ECDH if (type & SSL_kEECDH) { /* XXX: For now, we only support named (not generic) curves. * In this situation, the serverKeyExchange message has: * [1 byte CurveType], [2 byte CurveName] * [1 byte length of encoded point], followed by * the actual encoded point itself */ *p = NAMED_CURVE_TYPE; p += 1; *p = 0; p += 1; *p = curve_id; p += 1; *p = encodedlen; p += 1; memcpy((unsigned char*)p, (unsigned char *)encodedPoint, encodedlen); OPENSSL_free(encodedPoint); p += encodedlen; } #endif #ifndef OPENSSL_NO_PSK if (type & SSL_kPSK) { /* copy PSK identity hint */ s2n(strlen(s->ctx->psk_identity_hint), p); strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); p+=strlen(s->ctx->psk_identity_hint); } #endif /* not anonymous */ if (pkey != NULL) { Loading Loading @@ -991,6 +1195,25 @@ int dtls1_send_server_key_exchange(SSL *s) n+=i+2; } else #endif #if !defined(OPENSSL_NO_ECDSA) if (pkey->type == EVP_PKEY_EC) { /* let's do ECDSA */ EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(d[4]),n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA); goto err; } s2n(i,p); n+=i+2; } else #endif { /* Is this error check actually needed? */ Loading Loading @@ -1018,6 +1241,10 @@ int dtls1_send_server_key_exchange(SSL *s) f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: #ifndef OPENSSL_NO_ECDH if (encodedPoint != NULL) OPENSSL_free(encodedPoint); BN_CTX_free(bn_ctx); #endif EVP_MD_CTX_cleanup(&md_ctx); return(-1); } Loading