[openssl-dev] Memory leak in application when we use ECDH
Mody, Darshan (Darshan)
darshanmody at avaya.com
Wed Mar 15 05:44:54 UTC 2017
Hi,
We have observed memory leak when we register for ECDH callback(SSL_set_tmp_ecdh_callback). While performing negative testing with load we find that the applications starts leaking memory.
Further checking the Openssl implementation in the s3_srvr.c file (openssl version 1.0.2). I find that a pointer is not deleted after copying EC_KEY from the application or EC_KEY_new being called.
I suspect the below code.
if (type & SSL_kEECDH) {
const EC_GROUP *group;
ecdhp = cert->ecdh_tmp;
if (s->cert->ecdh_tmp_auto) {
/* Get NID of appropriate shared curve */
int nid = tls1_shared_curve(s, -2);
if (nid != NID_undef)
ecdhp = EC_KEY_new_by_curve_name(nid); <-- Even memory allocated in this case is not de-allocated.
} else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) {
ecdhp = s->cert->ecdh_tmp_cb(s, <-- Application is responsible for the EC_KEY and its memory
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_SSL3_SEND_SERVER_KEY_EXCHANGE,
SSL_R_MISSING_TMP_ECDH_KEY);
goto f_err;
}
if (s->s3->tmp.ecdh != NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Duplicate the ECDH structure. */
if (ecdhp == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB);
goto err;
}
if (s->cert->ecdh_tmp_auto)
ecdh = ecdhp;
else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { <-- Once the key is duplicated the memory for the application should be released?
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB);
goto err;
}
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_SSL3_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_SSL3_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_SSL3_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_SSL3_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_SSL3_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_SSL3_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
Thanks for your help in advance
Regards
Darshan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-dev/attachments/20170315/0379e198/attachment-0001.html>
More information about the openssl-dev
mailing list