[Asterisk-code-review] dtls: Add support for ephemeral DTLS certificates (asterisk[master])

Sean Bright asteriskteam at digium.com
Fri Sep 29 10:16:25 CDT 2017


Sean Bright has uploaded this change for review. ( https://gerrit.asterisk.org/6641


Change subject: dtls: Add support for ephemeral DTLS certificates
......................................................................

dtls: Add support for ephemeral DTLS certificates

This mimics the behavior of Chrome and Firefox and creates an ephemeral
X.509 certificate for each DTLS session.

Currently, the only supported key type is ECDSA because of its faster
generation time, but other key types can be added in the future as
necessary.

Change-Id: I5122e5f4b83c6320cc17407a187fcf491daf30b4
---
M channels/chan_sip.c
M configs/samples/pjsip.conf.sample
M configs/samples/sip.conf.sample
M include/asterisk/rtp_engine.h
M main/rtp_engine.c
M res/res_pjsip.c
M res/res_pjsip/pjsip_configuration.c
M res/res_rtp_asterisk.c
8 files changed, 336 insertions(+), 74 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/41/6641/1

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 8a30e0c..e31ba9b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -32398,7 +32398,8 @@
 	default_tls_cfg.cipher = ast_strdup("");
 	default_tls_cfg.cafile = ast_strdup("");
 	default_tls_cfg.capath = ast_strdup("");
-	/* Using the same idea fro DTLS as the code block above for TLS */
+	/* Using the same idea for DTLS as the code block above for TLS */
+	default_dtls_cfg.certtype = ast_strdup("file");
 	default_dtls_cfg.certfile = ast_strdup("");
 	default_dtls_cfg.pvtfile = ast_strdup("");
 	default_dtls_cfg.cipher = ast_strdup("");
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 9a2592b..436bb1a 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -744,6 +744,8 @@
                 ; "no")
 ;dtls_rekey=0   ; Interval at which to renegotiate the TLS session and rekey
                 ; the SRTP session (default: "0")
+;dtls_cert_type=        ; 'file' or 'ecdsa' depending on the type of certificate
+                        ; you want to use (default: "file")
 ;dtls_cert_file=        ; Path to certificate file to present to peer (default:
                         ; "")
 ;dtls_private_key=      ; Path to private key for certificate file (default:
diff --git a/configs/samples/sip.conf.sample b/configs/samples/sip.conf.sample
index 9b52ec0..a813ff0 100644
--- a/configs/samples/sip.conf.sample
+++ b/configs/samples/sip.conf.sample
@@ -1342,6 +1342,7 @@
 ; dtlsenable
 ; dtlsverify
 ; dtlsrekey
+; dtlscerttype
 ; dtlscertfile
 ; dtlsprivatekey
 ; dtlscipher
@@ -1369,6 +1370,11 @@
 ;				     ; A value of 'certificate' will perform ONLY certficiate verification
 ; dtlsrekey = 60                     ; Interval at which to renegotiate the TLS session and rekey the SRTP session
 ;                                    ; If this is not set or the value provided is 0 rekeying will be disabled
+; dtlscerttype = <file|ecdsa>        ; The type of certificate to use:
+;				     ; * A value of 'file' means to use the values provided by dtlscertfile,
+;				     ;   dtlscafile, dtlscapath, and dtlsprivatekey.
+;				     ; * A value of 'ecdsa' means to generate an ephemeral ECDSA key and X.509
+;				     ;   certificate for each DTLS session
 ; dtlscertfile = file                ; Path to certificate file to present
 ; dtlsprivatekey = file              ; Path to private key for certificate file
 ; dtlscipher = <SSL cipher string>   ; Cipher to use for TLS negotiation
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index 3ceac84..79e8ed3 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -508,6 +508,7 @@
 	char *cipher;                          /*!< Cipher to use */
 	char *cafile;                          /*!< Certificate authority file */
 	char *capath;                          /*!< Path to certificate authority */
+	char *certtype;                        /*!< The type of certificate (file or ecdsa) */
 };
 
 /*! \brief Structure that represents the optional DTLS SRTP support within an RTP engine */
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 226b229..7443c08 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -2717,6 +2717,13 @@
 		if (sscanf(value, "%30u", &dtls_cfg->rekey) != 1) {
 			return -1;
 		}
+	} else if (!strcasecmp(name, "dtlscerttype")) {
+		if (!ast_strlen_zero(value) && strcasecmp(value, "file") && strcasecmp(value, "ecdsa")) {
+			ast_log(LOG_ERROR, "%s must be either 'file' or 'ecdsa'\n", name);
+			return -1;
+		}
+		ast_free(dtls_cfg->certtype);
+		dtls_cfg->certtype = ast_strdup(value);
 	} else if (!strcasecmp(name, "dtlscertfile")) {
 		if (!ast_strlen_zero(value) && !ast_file_is_readable(value)) {
 			ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
@@ -2778,6 +2785,7 @@
 	dst_cfg->rekey = src_cfg->rekey;
 	dst_cfg->suite = src_cfg->suite;
 	dst_cfg->hash = src_cfg->hash;
+	dst_cfg->certtype = ast_strdup(src_cfg->certtype);
 	dst_cfg->certfile = ast_strdup(src_cfg->certfile);
 	dst_cfg->pvtfile = ast_strdup(src_cfg->pvtfile);
 	dst_cfg->cipher = ast_strdup(src_cfg->cipher);
@@ -2788,6 +2796,8 @@
 
 void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
 {
+	ast_free(dtls_cfg->certtype);
+	dtls_cfg->certtype = NULL;
 	ast_free(dtls_cfg->certfile);
 	dtls_cfg->certfile = NULL;
 	ast_free(dtls_cfg->pvtfile);
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 6c1f776..0419d9a 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -765,6 +765,24 @@
 						If this is not set or the value provided is 0 rekeying will be disabled.
 					</para></description>
 				</configOption>
+				<configOption name="dtls_cert_type" default="file">
+					<synopsis>The type of DTLS certificate to present to peer</synopsis>
+					<description><para>
+						Specifies whether to use the X.509 certificate provided with the
+						<replaceable>dtls_cert_file</replaceable>, <replaceable>dtls_ca_file</replaceable>,
+						and <replaceable>dtls_private_key</replaceable> options, or a newly generated one
+						for each session. This option only applies if <replaceable>media_encryption</replaceable>
+						is set to <literal>dtls</literal>.
+					</para></description>
+					<enumlist>
+						<enum name="file"><para>
+							res_pjsip will use the configured certificate files.
+						</para></enum>
+						<enum name="ecdsa"><para>
+							res_pjsip will generate an ephemeral certificate.
+						</para></enum>
+					</enumlist>
+				</configOption>
 				<configOption name="dtls_cert_file">
 					<synopsis>Path to certificate file to present to peer</synopsis>
 					<description><para>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 3a752c9..41147fa 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -986,6 +986,13 @@
 		buf, "%u", endpoint->media.rtp.dtls_cfg.rekey) >=0 ? 0 : -1;
 }
 
+static int dtlscerttype_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+	const struct ast_sip_endpoint *endpoint = obj;
+	*buf = ast_strdup(endpoint->media.rtp.dtls_cfg.certtype);
+	return 0;
+}
+
 static int dtlscertfile_to_str(const void *obj, const intptr_t *args, char **buf)
 {
 	const struct ast_sip_endpoint *endpoint = obj;
@@ -1363,9 +1370,11 @@
 		endpoint->media.rtp.dtls_cfg.default_setup = AST_RTP_DTLS_SETUP_ACTPASS;
 		endpoint->media.rtp.dtls_cfg.verify = AST_RTP_DTLS_VERIFY_FINGERPRINT;
 
-		if (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile)) {
+		if ((ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certtype)
+			|| !strcasecmp(endpoint->media.rtp.dtls_cfg.certtype, "file"))
+		   && ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile)) {
 			ast_log(LOG_ERROR, "WebRTC can't be enabled on endpoint '%s' - a DTLS cert "
-				"has not been specified", ast_sorcery_object_get_id(endpoint));
+					"has not been specified", ast_sorcery_object_get_id(endpoint));
 			return -1;
 		}
 	}
@@ -1962,6 +1971,7 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_engine", "asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.rtp.engine));
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_verify", "no", dtls_handler, dtlsverify_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_rekey", "0", dtls_handler, dtlsrekey_to_str, NULL, 0, 0);
+	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_type", "file", dtls_handler, dtlscerttype_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cert_file", "", dtls_handler, dtlscertfile_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_private_key", "", dtls_handler, dtlsprivatekey_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_cipher", "", dtls_handler, dtlscipher_to_str, NULL, 0, 0);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 7bf5b00..68c0551 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -1592,14 +1592,283 @@
 	return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup);
 }
 
+static const SSL_METHOD *get_dtls_method(void)
+{
+#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
+	return DTLSv1_method();
+#else
+	return DTLS_method();
+#endif
+}
+
+struct dtls_cert_info {
+	EVP_PKEY *private_key;
+	X509 *certificate;
+};
+
+#ifdef HAVE_OPENSSL_EC
+
+static void configure_dhparams(const struct ast_rtp *rtp, const struct ast_rtp_dtls_cfg *dtls_cfg)
+{
+	EC_KEY *ecdh;
+
+	if (!ast_strlen_zero(dtls_cfg->pvtfile)) {
+		BIO *bio = BIO_new_file(dtls_cfg->pvtfile, "r");
+		if (bio) {
+			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+			if (dh) {
+				if (SSL_CTX_set_tmp_dh(rtp->ssl_ctx, dh)) {
+					long options = SSL_OP_CIPHER_SERVER_PREFERENCE |
+						SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE;
+					options = SSL_CTX_set_options(rtp->ssl_ctx, options);
+					ast_verb(2, "DTLS DH initialized, PFS enabled\n");
+				}
+				DH_free(dh);
+			}
+			BIO_free(bio);
+		}
+	}
+
+	/* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */
+	ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+	if (ecdh) {
+		if (SSL_CTX_set_tmp_ecdh(rtp->ssl_ctx, ecdh)) {
+			#ifndef SSL_CTRL_SET_ECDH_AUTO
+				#define SSL_CTRL_SET_ECDH_AUTO 94
+			#endif
+			/* SSL_CTX_set_ecdh_auto(rtp->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */
+			if (SSL_CTX_ctrl(rtp->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) {
+				ast_verb(2, "DTLS ECDH initialized (automatic), faster PFS enabled\n");
+			} else {
+				ast_verb(2, "DTLS ECDH initialized (secp256r1), faster PFS enabled\n");
+			}
+		}
+		EC_KEY_free(ecdh);
+	}
+}
+
+static int create_ephemeral_ec_keypair(EVP_PKEY **keypair)
+{
+	EC_KEY *eckey = NULL;
+	EC_GROUP *group = NULL;
+
+	group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+	if (!group) {
+		goto error;
+	}
+
+	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+	EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
+
+	eckey = EC_KEY_new();
+	if (!eckey) {
+		goto error;
+	}
+
+	if (!EC_KEY_set_group(eckey, group)) {
+		goto error;
+	}
+
+	if (!EC_KEY_generate_key(eckey)) {
+		goto error;
+	}
+
+	*keypair = EVP_PKEY_new();
+	if (!*keypair) {
+		goto error;
+	}
+
+	EVP_PKEY_assign_EC_KEY(*keypair, eckey);
+	EC_GROUP_free(group);
+
+	return 0;
+
+error:
+	EC_KEY_free(eckey);
+	EC_GROUP_free(group);
+
+	return -1;
+}
+
+/* From OpenSSL's x509 command */
+#define SERIAL_RAND_BITS 159
+
+static int create_ephemeral_certificate(EVP_PKEY *keypair, X509 **certificate)
+{
+	X509 *cert = NULL;
+	BIGNUM *serial = NULL;
+	X509_NAME *name = NULL;
+
+	cert = X509_new();
+	if (!cert) {
+		goto error;
+	}
+
+	if (!X509_set_version(cert, 2)) {
+		goto error;
+	}
+
+	/* Set the public key */
+	X509_set_pubkey(cert, keypair);
+
+	/* Generate a random serial number */
+	if (!(serial = BN_new())
+	   || !BN_rand(serial, SERIAL_RAND_BITS, -1, 0)
+	   || !BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(cert))) {
+		goto error;
+	}
+
+	/*
+	 * Validity period - Current Chrome & Firefox make it 31 days starting
+	 * with yesterday at the current time, so we will do the same.
+	 */
+	if (!X509_time_adj_ex(X509_get_notBefore(cert), -1, 0, NULL)
+	   || !X509_time_adj_ex(X509_get_notAfter(cert), 30, 0, NULL)) {
+		goto error;
+	}
+
+	/* Set the name and issuer */
+	if (!(name = X509_get_subject_name(cert))
+	   || !X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
+									  (unsigned char *) "asterisk", -1, -1, 0)
+	   || !X509_set_issuer_name(cert, name)) {
+		goto error;
+	}
+
+	/* Sign it */
+	if (!X509_sign(cert, keypair, EVP_sha256())) {
+		goto error;
+	}
+
+	*certificate = cert;
+
+	return 0;
+
+error:
+	BN_free(serial);
+	X509_free(cert);
+
+	return -1;
+}
+
+static int create_certificate_ephemeral(struct ast_rtp_instance *instance,
+										const struct ast_rtp_dtls_cfg *dtls_cfg,
+										struct dtls_cert_info *cert_info)
+{
+	/* Make sure these are initialized */
+	cert_info->private_key = NULL;
+	cert_info->certificate = NULL;
+
+	if (create_ephemeral_ec_keypair(&cert_info->private_key)) {
+		ast_log(LOG_ERROR, "Failed to create ephemeral ECDSA keypair\n");
+		goto error;
+	}
+
+	if (create_ephemeral_certificate(cert_info->private_key, &cert_info->certificate)) {
+		ast_log(LOG_ERROR, "Failed to create ephemeral X509 certificate\n");
+		goto error;
+	}
+
+	return 0;
+
+  error:
+	X509_free(cert_info->certificate);
+	EVP_PKEY_free(cert_info->private_key);
+
+	return -1;
+}
+
+#else
+
+static void configure_dhparams(const struct ast_rtp *rtp, const struct ast_rtp_dtls_cfg *dtls_cfg)
+{
+}
+
+static int create_certificate_ephemeral(struct ast_rtp_instance *instance,
+										const struct ast_rtp_dtls_cfg *dtls_cfg,
+										struct dtls_cert_info *cert_info)
+{
+	ast_log(LOG_ERROR, "Your version of OpenSSL does not support ECDSA keys\n");
+	return -1;
+}
+
+#endif /* HAVE_OPENSSL_EC */
+
+static int create_certificate_from_file(struct ast_rtp_instance *instance,
+										const struct ast_rtp_dtls_cfg *dtls_cfg,
+										struct dtls_cert_info *cert_info)
+{
+	FILE *fp;
+	BIO *certbio = NULL;
+	EVP_PKEY *private_key = NULL;
+	X509 *cert = NULL;
+	char *private_key_file = ast_strlen_zero(dtls_cfg->pvtfile) ? dtls_cfg->certfile : dtls_cfg->pvtfile;
+
+	fp = fopen(private_key_file, "r");
+	if (!fp) {
+		ast_log(LOG_ERROR, "Failed to read private key from file '%s': %s\n", private_key_file, strerror(errno));
+		goto error;
+	}
+
+	if (!PEM_read_PrivateKey(fp, &private_key, NULL, NULL)) {
+		ast_log(LOG_ERROR, "Failed to read private key from PEM file '%s'\n", private_key_file);
+		fclose(fp);
+		goto error;
+	}
+
+	if (fclose(fp)) {
+		ast_log(LOG_ERROR, "Failed to close private key file '%s': %s\n", private_key_file, strerror(errno));
+		goto error;
+	}
+
+	certbio = BIO_new(BIO_s_file());
+	if (!certbio) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for certificate fingerprinting on RTP instance '%p'\n",
+				instance);
+		goto error;
+	}
+
+	if (!BIO_read_filename(certbio, dtls_cfg->certfile)
+	   || !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
+		ast_log(LOG_ERROR, "Failed to read certificate from file '%s'\n", dtls_cfg->certfile);
+		goto error;
+	}
+
+	cert_info->private_key = private_key;
+	cert_info->certificate = cert;
+
+	BIO_free_all(certbio);
+
+	return 0;
+
+error:
+	X509_free(cert);
+	BIO_free_all(certbio);
+	EVP_PKEY_free(private_key);
+
+	return -1;
+}
+
+static int load_dtls_certificate(struct ast_rtp_instance *instance,
+								 const struct ast_rtp_dtls_cfg *dtls_cfg,
+								 struct dtls_cert_info *cert_info)
+{
+	if (!ast_strlen_zero(dtls_cfg->certfile)
+	   && (ast_strlen_zero(dtls_cfg->certtype) || !strcasecmp(dtls_cfg->certtype, "file"))) {
+		return create_certificate_from_file(instance, dtls_cfg, cert_info);
+	} else if (!strcasecmp(dtls_cfg->certtype, "ecdsa")) {
+		return create_certificate_ephemeral(instance, dtls_cfg, cert_info);
+	} else {
+		return -1;
+	}
+}
+
 /*! \pre instance is locked */
 static int ast_rtp_dtls_set_configuration(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	struct dtls_cert_info cert_info = { 0 };
 	int res;
-#ifdef HAVE_OPENSSL_EC
-	EC_KEY *ecdh;
-#endif
 
 	if (!dtls_cfg->enabled) {
 		return 0;
@@ -1614,53 +1883,14 @@
 		return 0;
 	}
 
-#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
-	rtp->ssl_ctx = SSL_CTX_new(DTLSv1_method());
-#else
-	rtp->ssl_ctx = SSL_CTX_new(DTLS_method());
-#endif
+	rtp->ssl_ctx = SSL_CTX_new(get_dtls_method());
 	if (!rtp->ssl_ctx) {
 		return -1;
 	}
 
 	SSL_CTX_set_read_ahead(rtp->ssl_ctx, 1);
 
-#ifdef HAVE_OPENSSL_EC
-
-	if (!ast_strlen_zero(dtls_cfg->pvtfile)) {
-		BIO *bio = BIO_new_file(dtls_cfg->pvtfile, "r");
-		if (bio != NULL) {
-			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
-			if (dh != NULL) {
-				if (SSL_CTX_set_tmp_dh(rtp->ssl_ctx, dh)) {
-					long options = SSL_OP_CIPHER_SERVER_PREFERENCE |
-						SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE;
-					options = SSL_CTX_set_options(rtp->ssl_ctx, options);
-					ast_verb(2, "DTLS DH initialized, PFS enabled\n");
-				}
-				DH_free(dh);
-			}
-			BIO_free(bio);
-		}
-	}
-	/* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */
-	ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-	if (ecdh != NULL) {
-		if (SSL_CTX_set_tmp_ecdh(rtp->ssl_ctx, ecdh)) {
-			#ifndef SSL_CTRL_SET_ECDH_AUTO
-				#define SSL_CTRL_SET_ECDH_AUTO 94
-			#endif
-			/* SSL_CTX_set_ecdh_auto(rtp->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */
-			if (SSL_CTX_ctrl(rtp->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) {
-				ast_verb(2, "DTLS ECDH initialized (automatic), faster PFS enabled\n");
-			} else {
-				ast_verb(2, "DTLS ECDH initialized (secp256r1), faster PFS enabled\n");
-			}
-		}
-		EC_KEY_free(ecdh);
-	}
-
-#endif /* #ifdef HAVE_OPENSSL_EC */
+	configure_dhparams(rtp, dtls_cfg);
 
 	rtp->dtls_verify = dtls_cfg->verify;
 
@@ -1679,25 +1909,22 @@
 
 	rtp->local_hash = dtls_cfg->hash;
 
-	if (!ast_strlen_zero(dtls_cfg->certfile)) {
-		char *private = ast_strlen_zero(dtls_cfg->pvtfile) ? dtls_cfg->certfile : dtls_cfg->pvtfile;
-		BIO *certbio;
-		X509 *cert = NULL;
+	if (!load_dtls_certificate(instance, dtls_cfg, &cert_info)) {
 		const EVP_MD *type;
 		unsigned int size, i;
 		unsigned char fingerprint[EVP_MAX_MD_SIZE];
 		char *local_fingerprint = rtp->local_fingerprint;
 
-		if (!SSL_CTX_use_certificate_file(rtp->ssl_ctx, dtls_cfg->certfile, SSL_FILETYPE_PEM)) {
+		if (!SSL_CTX_use_certificate(rtp->ssl_ctx, cert_info.certificate)) {
 			ast_log(LOG_ERROR, "Specified certificate file '%s' for RTP instance '%p' could not be used\n",
 				dtls_cfg->certfile, instance);
 			return -1;
 		}
 
-		if (!SSL_CTX_use_PrivateKey_file(rtp->ssl_ctx, private, SSL_FILETYPE_PEM) ||
-		    !SSL_CTX_check_private_key(rtp->ssl_ctx)) {
-			ast_log(LOG_ERROR, "Specified private key file '%s' for RTP instance '%p' could not be used\n",
-				private, instance);
+		if (!SSL_CTX_use_PrivateKey(rtp->ssl_ctx, cert_info.private_key)
+		    || !SSL_CTX_check_private_key(rtp->ssl_ctx)) {
+			ast_log(LOG_ERROR, "Specified private key file for RTP instance '%p' could not be used\n",
+					instance);
 			return -1;
 		}
 
@@ -1711,22 +1938,9 @@
 			return -1;
 		}
 
-		if (!(certbio = BIO_new(BIO_s_file()))) {
-			ast_log(LOG_ERROR, "Failed to allocate memory for certificate fingerprinting on RTP instance '%p'\n",
-				instance);
-			return -1;
-		}
-
-		if (!BIO_read_filename(certbio, dtls_cfg->certfile) ||
-		    !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL)) ||
-		    !X509_digest(cert, type, fingerprint, &size) ||
-		    !size) {
+		if (!X509_digest(cert_info.certificate, type, fingerprint, &size) || !size) {
 			ast_log(LOG_ERROR, "Could not produce fingerprint from certificate '%s' for RTP instance '%p'\n",
-				dtls_cfg->certfile, instance);
-			BIO_free_all(certbio);
-			if (cert) {
-				X509_free(cert);
-			}
+					dtls_cfg->certfile, instance);
 			return -1;
 		}
 
@@ -1735,10 +1949,10 @@
 			local_fingerprint += 3;
 		}
 
-		*(local_fingerprint-1) = 0;
+		*(local_fingerprint - 1) = 0;
 
-		BIO_free_all(certbio);
-		X509_free(cert);
+		EVP_PKEY_free(cert_info.private_key);
+		X509_free(cert_info.certificate);
 	}
 
 	if (!ast_strlen_zero(dtls_cfg->cipher)) {

-- 
To view, visit https://gerrit.asterisk.org/6641
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5122e5f4b83c6320cc17407a187fcf491daf30b4
Gerrit-Change-Number: 6641
Gerrit-PatchSet: 1
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170929/aa024678/attachment-0001.html>


More information about the asterisk-code-review mailing list