Index: /pjproject/trunk/pjlib/include/pj/config.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/config.h	(revision 5471)
+++ /pjproject/trunk/pjlib/include/pj/config.h	(revision 5472)
@@ -888,4 +888,14 @@
 #ifndef PJ_SSL_SOCK_OSSL_CIPHERS
 #  define PJ_SSL_SOCK_OSSL_CIPHERS   "HIGH:-COMPLEMENTOFDEFAULT"
+#endif
+
+
+/**
+ * Define the maximum number of curves supported by the secure socket.
+ *
+ * Default: 32
+ */
+#ifndef PJ_SSL_SOCK_MAX_CURVES
+#  define PJ_SSL_SOCK_MAX_CURVES   32
 #endif
 
Index: /pjproject/trunk/pjlib/include/pj/ssl_sock.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/ssl_sock.h	(revision 5471)
+++ /pjproject/trunk/pjlib/include/pj/ssl_sock.h	(revision 5472)
@@ -402,4 +402,97 @@
 PJ_DECL(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name);
 
+/**
+ * Elliptic curves enumeration.
+ */
+typedef enum pj_ssl_curve
+{
+	PJ_TLS_UNKNOWN_CURVE 		= 0,
+	PJ_TLS_CURVE_SECT163K1		= 1,
+	PJ_TLS_CURVE_SECT163R1		= 2,
+	PJ_TLS_CURVE_SECT163R2		= 3,
+	PJ_TLS_CURVE_SECT193R1		= 4,
+	PJ_TLS_CURVE_SECT193R2		= 5,
+	PJ_TLS_CURVE_SECT233K1		= 6,
+	PJ_TLS_CURVE_SECT233R1		= 7,
+	PJ_TLS_CURVE_SECT239K1		= 8,
+	PJ_TLS_CURVE_SECT283K1		= 9,
+	PJ_TLS_CURVE_SECT283R1		= 10,
+	PJ_TLS_CURVE_SECT409K1		= 11,
+	PJ_TLS_CURVE_SECT409R1		= 12,
+	PJ_TLS_CURVE_SECT571K1		= 13,
+	PJ_TLS_CURVE_SECT571R1		= 14,
+	PJ_TLS_CURVE_SECP160K1		= 15,
+	PJ_TLS_CURVE_SECP160R1		= 16,
+	PJ_TLS_CURVE_SECP160R2		= 17,
+	PJ_TLS_CURVE_SECP192K1		= 18,
+	PJ_TLS_CURVE_SECP192R1		= 19,
+	PJ_TLS_CURVE_SECP224K1		= 20,
+	PJ_TLS_CURVE_SECP224R1		= 21,
+	PJ_TLS_CURVE_SECP256K1		= 22,
+	PJ_TLS_CURVE_SECP256R1		= 23,
+	PJ_TLS_CURVE_SECP384R1		= 24,
+	PJ_TLS_CURVE_SECP521R1		= 25,
+	PJ_TLS_CURVE_BRAINPOOLP256R1	= 26,
+	PJ_TLS_CURVE_BRAINPOOLP384R1	= 27,
+	PJ_TLS_CURVE_BRAINPOOLP512R1	= 28,
+	PJ_TLS_CURVE_ARBITRARY_EXPLICIT_PRIME_CURVES	= 0XFF01,
+	PJ_TLS_CURVE_ARBITRARY_EXPLICIT_CHAR2_CURVES	= 0XFF02
+} pj_ssl_curve;
+
+/**
+ * Get curve list supported by SSL/TLS backend.
+ *
+ * @param curves	The curves buffer to receive curve list.
+ * @param curves_num	Maximum number of curves to be received.
+ *
+ * @return		PJ_SUCCESS when successful.
+ */
+PJ_DECL(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[],
+					         unsigned *curve_num);
+
+/**
+ * Check if the specified curve is supported by SSL/TLS backend.
+ *
+ * @param curve		The curve.
+ *
+ * @return		PJ_TRUE when supported.
+ */
+PJ_DECL(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve);
+
+
+/**
+ * Get curve name string.
+ *
+ * @param curve		The curve.
+ *
+ * @return		The curve name or NULL if curve is not recognized/
+ *			supported.
+ */
+PJ_DECL(const char*) pj_ssl_curve_name(pj_ssl_curve curve);
+
+/**
+ * Get curve ID from curve name string. Note that on different backends
+ * (e.g. OpenSSL or Symbian implementation), curve names may not be
+ * equivalent for the same curve ID.
+ *
+ * @param curve_name	The curve name string.
+ *
+ * @return		The curve ID or PJ_TLS_UNKNOWN_CURVE if the curve
+ *			name string is not recognized/supported.
+ */
+PJ_DECL(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name);
+
+/*
+ * Entropy enumeration
+ */
+typedef enum pj_ssl_entropy
+{
+	PJ_SSL_ENTROPY_NONE	= 0,
+	PJ_SSL_ENTROPY_EGD	= 1,
+	PJ_SSL_ENTROPY_RANDOM	= 2,
+	PJ_SSL_ENTROPY_URANDOM	= 3,
+	PJ_SSL_ENTROPY_FILE	= 4,
+	PJ_SSL_ENTROPY_UNKNOWN	= 0x0F
+} pj_ssl_entropy_t;
 
 /**
@@ -771,4 +864,49 @@
 
     /**
+     * Number of curves contained in the specified curve preference.
+     * If this is set to zero, then default curve list of the backend
+     * will be used.
+     *
+     * Default: 0 (zero).
+     */
+    unsigned curves_num;
+
+    /**
+     * Curves and order preference. The #pj_ssl_curve_get_availables()
+     * can be used to check the available curves supported by backend.
+     */
+    pj_ssl_curve *curves;
+
+    /**
+     * The supported signature algorithms. Set the sigalgs string
+     * using this form:
+     * "<DIGEST>+<ALGORITHM>:<DIGEST>+<ALGORITHM>"
+     * Digests are: "RSA", "DSA" or "ECDSA"
+     * Algorithms are: "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512"
+     * Example: "ECDSA+SHA256:RSA+SHA256"
+     */
+    pj_str_t	sigalgs;
+
+    /**
+     * Reseed random number generator.
+     * For type #PJ_SSL_ENTROPY_FILE, parameter \a entropy_path
+     * must be set to a file.
+     * For type #PJ_SSL_ENTROPY_EGD, parameter \a entropy_path
+     * must be set to a socket.
+     *
+     * Default value is PJ_SSL_ENTROPY_NONE.
+    */
+    pj_ssl_entropy_t	entropy_type;
+
+    /**
+     * When using a file/socket for entropy #PJ_SSL_ENTROPY_EGD or
+     * #PJ_SSL_ENTROPY_FILE, \a entropy_path must contain the path
+     * to entropy socket/file.
+     *
+     * Default value is an empty string.
+     */
+    pj_str_t		entropy_path;
+
+    /**
      * Security negotiation timeout. If this is set to zero (both sec and 
      * msec), the negotiation doesn't have a timeout.
Index: /pjproject/trunk/pjlib/src/pj/ssl_sock_common.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/ssl_sock_common.c	(revision 5471)
+++ /pjproject/trunk/pjlib/src/pj/ssl_sock_common.c	(revision 5472)
@@ -68,7 +68,25 @@
     }
 
+    if (src->curves_num > 0) {
+	unsigned i;
+    	dst->curves = (pj_ssl_curve *)pj_pool_calloc(pool, src->curves_num,
+					   	     sizeof(pj_ssl_curve));
+	for (i = 0; i < src->curves_num; ++i)
+	    dst->curves[i] = src->curves[i];
+    }
+
     if (src->server_name.slen) {
         /* Server name must be null-terminated */
         pj_strdup_with_null(pool, &dst->server_name, &src->server_name);
+    }
+
+    if (src->sigalgs.slen) {
+    	/* Sigalgs name must be null-terminated */
+    	pj_strdup_with_null(pool, &dst->sigalgs, &src->sigalgs);
+    }
+
+    if (src->entropy_path.slen) {
+    	/* Path name must be null-terminated */
+    	pj_strdup_with_null(pool, &dst->entropy_path, &src->entropy_path);
     }
 }
Index: /pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 5471)
+++ /pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c	(revision 5472)
@@ -50,5 +50,11 @@
 #include <openssl/err.h>
 #include <openssl/x509v3.h>
-
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+
+#if !defined(OPENSSL_NO_EC)
+   extern int tls1_ec_nid2curve_id(int nid);
+   extern int tls1_ec_curve_id2nid(int curve_id);
+#endif
 
 #ifdef _MSC_VER
@@ -300,4 +306,11 @@
 } openssl_ciphers[PJ_SSL_SOCK_MAX_CIPHERS];
 
+/* OpenSSL available curves */
+static unsigned openssl_curves_num;
+static struct openssl_curves_t {
+    pj_ssl_curve    id;
+    const char	    *name;
+} openssl_curves[PJ_SSL_SOCK_MAX_CURVES];
+
 /* OpenSSL application data index */
 static int sslsock_idx;
@@ -329,5 +342,5 @@
 
     /* Init available ciphers */
-    if (openssl_cipher_num == 0) {
+    if (openssl_cipher_num == 0 || openssl_curves_num == 0) {
 	SSL_METHOD *meth = NULL;
 	SSL_CTX *ctx;
@@ -335,4 +348,6 @@
 	STACK_OF(SSL_CIPHER) *sk_cipher;
 	unsigned i, n;
+	int nid;
+	const char *cname;
 
 	meth = (SSL_METHOD*)SSLv23_server_method();
@@ -353,4 +368,5 @@
 
 	ssl = SSL_new(ctx);
+
 	sk_cipher = SSL_get_ciphers(ssl);
 
@@ -366,9 +382,34 @@
 	    openssl_ciphers[i].name = SSL_CIPHER_get_name(c);
 	}
+	openssl_cipher_num = n;
+
+	ssl->session = SSL_SESSION_new();
+
+#if !defined(OPENSSL_NO_EC)
+	openssl_curves_num = SSL_get_shared_curve(ssl,-1);
+	if (openssl_curves_num > PJ_ARRAY_SIZE(openssl_curves))
+	    openssl_curves_num = PJ_ARRAY_SIZE(openssl_curves);
+
+	for (i = 0; i < openssl_curves_num; i++) {
+	    nid = SSL_get_shared_curve(ssl, i);
+
+	    if (nid & TLSEXT_nid_unknown) {
+		cname = "curve unknown";
+		nid &= 0xFFFF;
+	    } else {
+		cname = EC_curve_nid2nist(nid);
+		if (!cname)
+		    cname = OBJ_nid2sn(nid);
+	    }
+
+	    openssl_curves[i].id   = tls1_ec_nid2curve_id(nid);
+	    openssl_curves[i].name = cname;
+	}
+#else
+	openssl_curves_num = 0;
+#endif
 
 	SSL_free(ssl);
 	SSL_CTX_free(ctx);
-
-	openssl_cipher_num = n;
     }
 
@@ -376,5 +417,5 @@
     sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL);
 
-    return PJ_SUCCESS;
+    return status;
 }
 
@@ -499,5 +540,10 @@
 /* Setting SSL sock cipher list */
 static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock);
-
+/* Setting SSL sock curves list */
+static pj_status_t set_curves_list(pj_ssl_sock_t *ssock);
+/* Setting sigalgs list */
+static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock);
+/* Setting entropy for rng */
+static void set_entropy(pj_ssl_sock_t *ssock);
 
 /* Create and initialize new SSL context and instance */
@@ -523,4 +569,6 @@
     /* Make sure OpenSSL library has been initialized */
     init_openssl();
+
+    set_entropy(ssock);
 
     if (ssock->param.proto == PJ_SSL_SOCK_PROTO_DEFAULT)
@@ -776,4 +824,14 @@
 	return status;
 
+    /* Set curve list */
+    status = set_curves_list(ssock);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Set sigalg list */
+    status = set_sigalgs(ssock);
+    if (status != PJ_SUCCESS)
+	return status;
+
     /* Setup SSL BIOs */
     ssock->ossl_rbio = BIO_new(BIO_s_mem());
@@ -940,4 +998,87 @@
 }
 
+static pj_status_t set_curves_list(pj_ssl_sock_t *ssock)
+{
+#if !defined(OPENSSL_NO_EC)
+    int ret;
+    int curves[PJ_SSL_SOCK_MAX_CURVES];
+    int cnt;
+
+    if (ssock->param.curves_num == 0)
+	return PJ_SUCCESS;
+
+    for (cnt = 0; cnt < ssock->param.curves_num; cnt++) {
+	curves[cnt] = tls1_ec_curve_id2nid(ssock->param.curves[cnt]);
+    }
+
+    if( ssock->ossl_ssl->server ) {
+	ret = SSL_set1_curves(ssock->ossl_ssl, curves,
+			      ssock->param.curves_num);
+	if (ret < 1)
+	    return GET_SSL_STATUS(ssock);
+    } else {
+	ret = SSL_CTX_set1_curves(ssock->ossl_ctx, curves,
+				  ssock->param.curves_num);
+	if (ret < 1)
+	    return GET_SSL_STATUS(ssock);
+    }
+
+    return PJ_SUCCESS;
+#else
+    return PJ_ENOTSUP;
+#endif
+}
+
+static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock)
+{
+    int ret;
+
+    if (ssock->param.sigalgs.ptr && ssock->param.sigalgs.slen) {
+	if (ssock->is_server) {
+	    ret = SSL_set1_client_sigalgs_list(ssock->ossl_ssl,
+	    				       ssock->param.sigalgs.ptr);
+	} else {
+	    ret = SSL_set1_sigalgs_list(ssock->ossl_ssl,
+	    				ssock->param.sigalgs.ptr);
+	}
+
+	if (ret < 1)
+	    return GET_SSL_STATUS(ssock);
+    }
+
+    return PJ_SUCCESS;
+}
+
+static void set_entropy(pj_ssl_sock_t *ssock)
+{
+    int ret;
+
+    switch (ssock->param.entropy_type) {
+#ifndef OPENSSL_NO_EGD
+	case PJ_SSL_ENTROPY_EGD:
+	    ret = RAND_egd(ssock->param.entropy_path.ptr);
+	    break;
+#endif
+	case PJ_SSL_ENTROPY_RANDOM:
+	    ret = RAND_load_file("/dev/random",255);
+	    break;
+	case PJ_SSL_ENTROPY_URANDOM:
+	    ret = RAND_load_file("/dev/urandom",255);
+	    break;
+	case PJ_SSL_ENTROPY_FILE:
+	    ret = RAND_load_file(ssock->param.entropy_path.ptr,255);
+	    break;
+	case PJ_SSL_ENTROPY_NONE:
+	    default:
+	    return;
+	    break;
+    }
+
+    if (ret < 0) {
+	PJ_LOG(3, (ssock->pool->obj_name, "SSL failed to reseed with "
+					  "entropy type %d",
+			  		  ssock->param.entropy_type));
+    }
+}
 
 /* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */
@@ -2232,4 +2373,83 @@
 }
 
+/* Get available curves. */
+PJ_DEF(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[],
+						unsigned *curve_num)
+{
+    unsigned i;
+
+    PJ_ASSERT_RETURN(curves && curve_num, PJ_EINVAL);
+
+    if (openssl_curves_num == 0) {
+	init_openssl();
+	shutdown_openssl();
+    }
+
+    if (openssl_curves_num == 0) {
+	*curve_num = 0;
+	return PJ_ENOTFOUND;
+    }
+
+    *curve_num = PJ_MIN(*curve_num, openssl_curves_num);
+
+    for (i = 0; i < *curve_num; ++i)
+    curves[i] = openssl_curves[i].id;
+
+    return PJ_SUCCESS;
+}
+
+/* Get curve name string. */
+PJ_DEF(const char*) pj_ssl_curve_name(pj_ssl_curve curve)
+{
+    unsigned i;
+
+    if (openssl_curves_num == 0) {
+	init_openssl();
+	shutdown_openssl();
+    }
+
+    for (i = 0; i < openssl_curves_num; ++i) {
+	if (curve == openssl_curves[i].id)
+	    return openssl_curves[i].name;
+    }
+
+    return NULL;
+}
+
+/* Get curve ID from curve name string. */
+PJ_DEF(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name)
+{
+    unsigned i;
+
+    if (openssl_curves_num == 0) {
+        init_openssl();
+        shutdown_openssl();
+    }
+
+    for (i = 0; i < openssl_curves_num; ++i) {
+        if (!pj_ansi_stricmp(openssl_curves[i].name, curve_name))
+            return openssl_curves[i].id;
+    }
+
+    return PJ_TLS_UNKNOWN_CURVE;
+}
+
+/* Check if the specified curve is supported by SSL/TLS backend. */
+PJ_DEF(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve)
+{
+    unsigned i;
+
+    if (openssl_curves_num == 0) {
+	init_openssl();
+	shutdown_openssl();
+    }
+
+    for (i = 0; i < openssl_curves_num; ++i) {
+	if (curve == openssl_curves[i].id)
+	    return PJ_TRUE;
+    }
+
+    return PJ_FALSE;
+}
 
 /*
Index: /pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h	(revision 5471)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h	(revision 5472)
@@ -142,4 +142,49 @@
 
     /**
+     * Number of curves contained in the specified curve preference.
+     * If this is set to zero, then default curve list of the backend
+     * will be used.
+     *
+     * Default: 0 (zero).
+     */
+    unsigned curves_num;
+
+    /**
+     * Curves and order preference. The #pj_ssl_curve_get_availables()
+     * can be used to check the available curves supported by backend.
+     */
+    pj_ssl_curve *curves;
+
+    /**
+     * The supported signature algorithms. Set the sigalgs string
+     * using this form:
+     * "<DIGEST>+<ALGORITHM>:<DIGEST>+<ALGORITHM>"
+     * Digests are: "RSA", "DSA" or "ECDSA"
+     * Algorithms are: "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512"
+     * Example: "ECDSA+SHA256:RSA+SHA256"
+     */
+    pj_str_t	sigalgs;
+
+    /**
+     * Reseed random number generator.
+     * For type #PJ_SSL_ENTROPY_FILE, parameter \a entropy_path
+     * must be set to a file.
+     * For type #PJ_SSL_ENTROPY_EGD, parameter \a entropy_path
+     * must be set to a socket.
+     *
+     * Default value is PJ_SSL_ENTROPY_NONE.
+    */
+    pj_ssl_entropy_t	entropy_type;
+
+    /**
+     * When using a file/socket for entropy #PJ_SSL_ENTROPY_EGD or
+     * #PJ_SSL_ENTROPY_FILE, \a entropy_path must contain the path
+     * to entropy socket/file.
+     *
+     * Default value is an empty string.
+     */
+    pj_str_t		entropy_path;
+
+    /**
      * Specifies TLS transport behavior on the server TLS certificate 
      * verification result:
@@ -293,4 +338,6 @@
     pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file);
     pj_strdup_with_null(pool, &dst->password, &src->password);
+    pj_strdup_with_null(pool, &dst->sigalgs, &src->sigalgs);
+    pj_strdup_with_null(pool, &dst->entropy_path, &src->entropy_path);
     if (src->ciphers_num) {
 	unsigned i;
@@ -299,4 +346,12 @@
 	for (i=0; i<src->ciphers_num; ++i)
 	    dst->ciphers[i] = src->ciphers[i];
+    }
+
+    if (src->curves_num) {
+	unsigned i;
+	dst->curves = (pj_ssl_curve*) pj_pool_calloc(pool, src->curves_num,
+						     sizeof(pj_ssl_curve));
+	for (i=0; i<src->curves_num; ++i)
+	    dst->curves[i] = src->curves[i];
     }
 }
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 5471)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 5472)
@@ -392,4 +392,9 @@
     ssock_param.ciphers_num = listener->tls_setting.ciphers_num;
     ssock_param.ciphers = listener->tls_setting.ciphers;
+    ssock_param.curves_num = listener->tls_setting.curves_num;
+    ssock_param.curves = listener->tls_setting.curves;
+    ssock_param.sigalgs = listener->tls_setting.sigalgs;
+    ssock_param.entropy_type = listener->tls_setting.entropy_type;
+    ssock_param.entropy_path = listener->tls_setting.entropy_path;
     ssock_param.reuse_addr = listener->tls_setting.reuse_addr;
     ssock_param.qos_type = listener->tls_setting.qos_type;
@@ -1071,4 +1076,9 @@
     ssock_param.ciphers_num = listener->tls_setting.ciphers_num;
     ssock_param.ciphers = listener->tls_setting.ciphers;
+    ssock_param.curves_num = listener->tls_setting.curves_num;
+    ssock_param.curves = listener->tls_setting.curves;
+    ssock_param.sigalgs = listener->tls_setting.sigalgs;
+    ssock_param.entropy_type = listener->tls_setting.entropy_type;
+    ssock_param.entropy_path = listener->tls_setting.entropy_path;
     ssock_param.qos_type = listener->tls_setting.qos_type;
     ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error;
