Add support for changing the TLS elliptic curve set.
This CL is almost identical to http://chromium-review.googlesource.com/c/611150
Bug: webrtc:8213
Change-Id: I21a8a0041a73b3171ed66b687dc47a579d45fe19
Reviewed-on: https://chromium-review.googlesource.com/653205
Commit-Queue: Diogo Real <diogor@google.com>
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Reviewed-by: Emad Omara <emadomara@webrtc.org>
Reviewed-by: Zeke Chin <tkchin@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Original-Commit-Position: refs/heads/master@{#19755}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 7bd1f1bb5bc747af7050b22b288eebd930b9e528
diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h
index 6a2b904..e23b705 100644
--- a/api/peerconnectioninterface.h
+++ b/api/peerconnectioninterface.h
@@ -195,12 +195,15 @@
std::string hostname;
// List of protocols to be used in the TLS ALPN extension.
std::vector<std::string> tls_alpn_protocols;
+ // List of elliptic curves to be used in the TLS elliptic curves extension.
+ std::vector<std::string> tls_elliptic_curves;
bool operator==(const IceServer& o) const {
return uri == o.uri && urls == o.urls && username == o.username &&
password == o.password && tls_cert_policy == o.tls_cert_policy &&
hostname == o.hostname &&
- tls_alpn_protocols == o.tls_alpn_protocols;
+ tls_alpn_protocols == o.tls_alpn_protocols &&
+ tls_elliptic_curves == o.tls_elliptic_curves;
}
bool operator!=(const IceServer& o) const { return !(*this == o); }
};
diff --git a/p2p/base/basicpacketsocketfactory.cc b/p2p/base/basicpacketsocketfactory.cc
index fe9eb4b..b0f464b 100644
--- a/p2p/base/basicpacketsocketfactory.cc
+++ b/p2p/base/basicpacketsocketfactory.cc
@@ -159,6 +159,7 @@
}
ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols);
+ ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves);
socket = ssl_adapter;
diff --git a/p2p/base/packetsocketfactory.h b/p2p/base/packetsocketfactory.h
index 34f568c..8ae0bd3 100644
--- a/p2p/base/packetsocketfactory.h
+++ b/p2p/base/packetsocketfactory.h
@@ -20,6 +20,7 @@
struct PacketSocketTcpOptions {
int opts;
std::vector<std::string> tls_alpn_protocols;
+ std::vector<std::string> tls_elliptic_curves;
};
class AsyncPacketSocket;
diff --git a/p2p/base/port_unittest.cc b/p2p/base/port_unittest.cc
index 0a53609..f47751f 100644
--- a/p2p/base/port_unittest.cc
+++ b/p2p/base/port_unittest.cc
@@ -536,7 +536,7 @@
return TurnPort::Create(
&main_, socket_factory, MakeNetwork(addr), 0, 0, username_, password_,
ProtocolAddress(server_addr, int_proto), kRelayCredentials, 0,
- std::string(), std::vector<std::string>());
+ std::string(), std::vector<std::string>(), std::vector<std::string>());
}
RelayPort* CreateGturnPort(const SocketAddress& addr,
ProtocolType int_proto, ProtocolType ext_proto) {
diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h
index eef4305..63d7c71 100644
--- a/p2p/base/portallocator.h
+++ b/p2p/base/portallocator.h
@@ -192,6 +192,7 @@
int priority = 0;
TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE;
std::vector<std::string> tls_alpn_protocols;
+ std::vector<std::string> tls_elliptic_curves;
};
class PortAllocatorSession : public sigslot::has_slots<> {
diff --git a/p2p/base/turnport.cc b/p2p/base/turnport.cc
index 68dae82..71a0311 100644
--- a/p2p/base/turnport.cc
+++ b/p2p/base/turnport.cc
@@ -222,7 +222,8 @@
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
- const std::vector<std::string>& tls_alpn_protocols)
+ const std::vector<std::string>& tls_alpn_protocols,
+ const std::vector<std::string>& tls_elliptic_curves)
: Port(thread,
RELAY_PORT_TYPE,
factory,
@@ -233,6 +234,7 @@
password),
server_address_(server_address),
tls_alpn_protocols_(tls_alpn_protocols),
+ tls_elliptic_curves_(tls_elliptic_curves),
credentials_(credentials),
socket_(NULL),
resolver_(NULL),
@@ -341,6 +343,7 @@
rtc::PacketSocketTcpOptions tcp_options;
tcp_options.opts = opts;
tcp_options.tls_alpn_protocols = tls_alpn_protocols_;
+ tcp_options.tls_elliptic_curves = tls_elliptic_curves_;
socket_ = socket_factory()->CreateClientTcpSocket(
rtc::SocketAddress(Network()->GetBestIP(), 0), server_address_.address,
proxy(), user_agent(), tcp_options);
diff --git a/p2p/base/turnport.h b/p2p/base/turnport.h
index 46200a9..4d9a811 100644
--- a/p2p/base/turnport.h
+++ b/p2p/base/turnport.h
@@ -70,10 +70,11 @@
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
- const std::vector<std::string>& tls_alpn_protocols) {
+ const std::vector<std::string>& tls_alpn_protocols,
+ const std::vector<std::string>& tls_elliptic_curves) {
return new TurnPort(thread, factory, network, min_port, max_port, username,
password, server_address, credentials, server_priority,
- origin, tls_alpn_protocols);
+ origin, tls_alpn_protocols, tls_elliptic_curves);
}
virtual ~TurnPort();
@@ -100,6 +101,10 @@
return tls_alpn_protocols_;
}
+ virtual std::vector<std::string> GetTlsEllipticCurves() const {
+ return tls_elliptic_curves_;
+ }
+
virtual void PrepareAddress();
virtual Connection* CreateConnection(
const Candidate& c, PortInterface::CandidateOrigin origin);
@@ -192,7 +197,8 @@
const RelayCredentials& credentials,
int server_priority,
const std::string& origin,
- const std::vector<std::string>& alpn_protocols);
+ const std::vector<std::string>& tls_alpn_protocols,
+ const std::vector<std::string>& tls_elliptic_curves);
private:
enum {
@@ -273,6 +279,7 @@
ProtocolAddress server_address_;
TlsCertPolicy tls_cert_policy_ = TlsCertPolicy::TLS_CERT_POLICY_SECURE;
std::vector<std::string> tls_alpn_protocols_;
+ std::vector<std::string> tls_elliptic_curves_;
RelayCredentials credentials_;
AttemptedServerSet attempted_server_addresses_;
diff --git a/p2p/base/turnport_unittest.cc b/p2p/base/turnport_unittest.cc
index 546c21e..a8e2937 100644
--- a/p2p/base/turnport_unittest.cc
+++ b/p2p/base/turnport_unittest.cc
@@ -263,7 +263,8 @@
RelayCredentials credentials(username, password);
turn_port_.reset(TurnPort::Create(
&main_, &socket_factory_, network, 0, 0, kIceUfrag1, kIcePwd1,
- server_address, credentials, 0, origin, std::vector<std::string>()));
+ server_address, credentials, 0, origin, std::vector<std::string>(),
+ std::vector<std::string>()));
// This TURN port will be the controlling.
turn_port_->SetIceRole(ICEROLE_CONTROLLING);
ConnectSignals();
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index fe2dfb6..992aee6 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -1445,7 +1445,7 @@
session_->allocator()->min_port(), session_->allocator()->max_port(),
session_->username(), session_->password(), *relay_port,
config.credentials, config.priority, session_->allocator()->origin(),
- config.tls_alpn_protocols);
+ config.tls_alpn_protocols, config.tls_elliptic_curves);
}
RTC_DCHECK(port != NULL);
port->SetTlsCertPolicy(config.tls_cert_policy);
diff --git a/pc/iceserverparsing.cc b/pc/iceserverparsing.cc
index 00e9f25..9b802fc 100644
--- a/pc/iceserverparsing.cc
+++ b/pc/iceserverparsing.cc
@@ -258,6 +258,7 @@
cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
}
config.tls_alpn_protocols = server.tls_alpn_protocols;
+ config.tls_elliptic_curves = server.tls_elliptic_curves;
turn_servers->push_back(config);
break;
diff --git a/rtc_base/openssladapter.cc b/rtc_base/openssladapter.cc
index 9164258..d944fa0 100644
--- a/rtc_base/openssladapter.cc
+++ b/rtc_base/openssladapter.cc
@@ -31,6 +31,7 @@
#include "webrtc/rtc_base/openssl.h"
#include "webrtc/rtc_base/safe_conversions.h"
#include "webrtc/rtc_base/sslroots.h"
+#include "webrtc/rtc_base/stringencode.h"
#include "webrtc/rtc_base/stringutils.h"
#include "webrtc/rtc_base/thread.h"
@@ -311,6 +312,10 @@
alpn_protocols_ = protos;
}
+void OpenSSLAdapter::SetEllipticCurves(const std::vector<std::string>& curves) {
+ elliptic_curves_ = curves;
+}
+
void OpenSSLAdapter::SetMode(SSLMode mode) {
RTC_DCHECK(!ssl_ctx_);
RTC_DCHECK(state_ == SSL_NONE);
@@ -445,6 +450,10 @@
}
}
+ if (!elliptic_curves_.empty()) {
+ SSL_set1_curves_list(ssl_, rtc::join(elliptic_curves_, ':').c_str());
+ }
+
// Now that the initial config is done, transfer ownership of |bio| to the
// SSL object. If ContinueSSL() fails, the bio will be freed in Cleanup().
SSL_set_bio(ssl_, bio, bio);
diff --git a/rtc_base/openssladapter.h b/rtc_base/openssladapter.h
index 9c6c344..6409c76 100644
--- a/rtc_base/openssladapter.h
+++ b/rtc_base/openssladapter.h
@@ -40,6 +40,7 @@
void SetIgnoreBadCert(bool ignore) override;
void SetAlpnProtocols(const std::vector<std::string>& protos) override;
+ void SetEllipticCurves(const std::vector<std::string>& curves) override;
void SetMode(SSLMode mode) override;
void SetIdentity(SSLIdentity* identity) override;
@@ -136,6 +137,8 @@
bool ignore_bad_cert_;
// List of protocols to be used in the TLS ALPN extension.
std::vector<std::string> alpn_protocols_;
+ // List of elliptic curves to be used in the TLS elliptic curves extension.
+ std::vector<std::string> elliptic_curves_;
bool custom_verification_succeeded_;
};
diff --git a/rtc_base/ssladapter.h b/rtc_base/ssladapter.h
index b30e176..922f42e 100644
--- a/rtc_base/ssladapter.h
+++ b/rtc_base/ssladapter.h
@@ -48,7 +48,9 @@
// TODO(juberti): Remove the opportunistic encryption mechanism in
// BasicPacketSocketFactory that uses this function.
virtual void SetIgnoreBadCert(bool ignore) = 0;
+
virtual void SetAlpnProtocols(const std::vector<std::string>& protos) = 0;
+ virtual void SetEllipticCurves(const std::vector<std::string>& curves) = 0;
// Do DTLS or TLS (default is TLS, if unspecified)
virtual void SetMode(SSLMode mode) = 0;
diff --git a/rtc_base/ssladapter_unittest.cc b/rtc_base/ssladapter_unittest.cc
index 5c61f6a..8e5d322 100644
--- a/rtc_base/ssladapter_unittest.cc
+++ b/rtc_base/ssladapter_unittest.cc
@@ -64,6 +64,10 @@
ssl_adapter_->SetAlpnProtocols(protos);
}
+ void SetEllipticCurves(const std::vector<std::string>& curves) {
+ ssl_adapter_->SetEllipticCurves(curves);
+ }
+
rtc::SocketAddress GetAddress() const {
return ssl_adapter_->GetLocalAddress();
}
@@ -290,6 +294,10 @@
client_->SetAlpnProtocols(protos);
}
+ void SetEllipticCurves(const std::vector<std::string>& curves) {
+ client_->SetEllipticCurves(curves);
+ }
+
void TestHandshake(bool expect_success) {
int rv;
@@ -450,6 +458,14 @@
TestTransfer("Hello, world!");
}
+// Test transfer with TLS Elliptic curves set to "X25519:P-256:P-384:P-521"
+TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSEllipticCurves) {
+ std::vector<std::string> elliptic_curves{"X25519", "P-256", "P-384", "P-521"};
+ SetEllipticCurves(elliptic_curves);
+ TestHandshake(true);
+ TestTransfer("Hello, world!");
+}
+
// Basic tests: DTLS
// Test that handshake works, using RSA
diff --git a/rtc_base/stringencode.cc b/rtc_base/stringencode.cc
index 93470b6..a4d594d 100644
--- a/rtc_base/stringencode.cc
+++ b/rtc_base/stringencode.cc
@@ -645,6 +645,28 @@
return true;
}
+std::string join(const std::vector<std::string>& source, char delimiter) {
+ if (source.size() == 0) {
+ return std::string();
+ }
+ // Find length of the string to be returned to pre-allocate memory.
+ size_t source_string_length = 0;
+ for (size_t i = 0; i < source.size(); ++i) {
+ source_string_length += source[i].length();
+ }
+
+ // Build the joined string.
+ std::string joined_string;
+ joined_string.reserve(source_string_length + source.size() - 1);
+ for (size_t i = 0; i < source.size(); ++i) {
+ if (i != 0) {
+ joined_string += delimiter;
+ }
+ joined_string += source[i];
+ }
+ return joined_string;
+}
+
size_t split(const std::string& source, char delimiter,
std::vector<std::string>* fields) {
RTC_DCHECK(fields);
diff --git a/rtc_base/stringencode.h b/rtc_base/stringencode.h
index 5296a9c..a4452c2 100644
--- a/rtc_base/stringencode.h
+++ b/rtc_base/stringencode.h
@@ -136,6 +136,10 @@
return s_transform(source, url_decode);
}
+// Joins the source vector of strings into a single string, with each
+// field in source being separated by delimiter. No trailing delimiter is added.
+std::string join(const std::vector<std::string>& source, char delimiter);
+
// Splits the source string into multiple fields separated by delimiter,
// with duplicates of delimiter creating empty fields.
size_t split(const std::string& source, char delimiter,
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index 8322410..c362d92 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -113,6 +113,10 @@
// List of protocols to be used in the TLS ALPN extension.
public final List<String> tlsAlpnProtocols;
+ // List of elliptic curves to be used in the TLS elliptic curves extension.
+ // Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
+ public final List<String> tlsEllipticCurves;
+
/** Convenience constructor for STUN servers. */
@Deprecated
public IceServer(String uri) {
@@ -132,22 +136,23 @@
@Deprecated
public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy,
String hostname) {
- this(uri, username, password, tlsCertPolicy, hostname, null);
+ this(uri, username, password, tlsCertPolicy, hostname, null, null);
}
private IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy,
- String hostname, List<String> tlsAlpnProtocols) {
+ String hostname, List<String> tlsAlpnProtocols, List<String> tlsEllipticCurves) {
this.uri = uri;
this.username = username;
this.password = password;
this.tlsCertPolicy = tlsCertPolicy;
this.hostname = hostname;
this.tlsAlpnProtocols = tlsAlpnProtocols;
+ this.tlsEllipticCurves = tlsEllipticCurves;
}
public String toString() {
return uri + " [" + username + ":" + password + "] [" + tlsCertPolicy + "] [" + hostname
- + "] [" + tlsAlpnProtocols + "]";
+ + "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "]";
}
public static Builder builder(String uri) {
@@ -161,6 +166,7 @@
private TlsCertPolicy tlsCertPolicy = TlsCertPolicy.TLS_CERT_POLICY_SECURE;
private String hostname = "";
private List<String> tlsAlpnProtocols;
+ private List<String> tlsEllipticCurves;
private Builder(String uri) {
this.uri = uri;
@@ -191,8 +197,14 @@
return this;
}
+ public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) {
+ this.tlsEllipticCurves = tlsEllipticCurves;
+ return this;
+ }
+
public IceServer createIceServer() {
- return new IceServer(uri, username, password, tlsCertPolicy, hostname, tlsAlpnProtocols);
+ return new IceServer(
+ uri, username, password, tlsCertPolicy, hostname, tlsAlpnProtocols, tlsEllipticCurves);
}
}
}
diff --git a/sdk/android/src/jni/pc/java_native_conversion.cc b/sdk/android/src/jni/pc/java_native_conversion.cc
index 799f67d..eb9892a 100644
--- a/sdk/android/src/jni/pc/java_native_conversion.cc
+++ b/sdk/android/src/jni/pc/java_native_conversion.cc
@@ -364,6 +364,8 @@
GetFieldID(jni, j_ice_server_class, "hostname", "Ljava/lang/String;");
jfieldID j_ice_server_tls_alpn_protocols_id = GetFieldID(
jni, j_ice_server_class, "tlsAlpnProtocols", "Ljava/util/List;");
+ jfieldID j_ice_server_tls_elliptic_curves_id = GetFieldID(
+ jni, j_ice_server_class, "tlsEllipticCurves", "Ljava/util/List;");
jstring uri = reinterpret_cast<jstring>(
GetObjectField(jni, j_ice_server, j_ice_server_uri_id));
jstring username = reinterpret_cast<jstring>(
@@ -376,6 +378,8 @@
GetObjectField(jni, j_ice_server, j_ice_server_hostname_id));
jobject tls_alpn_protocols = GetNullableObjectField(
jni, j_ice_server, j_ice_server_tls_alpn_protocols_id);
+ jobject tls_elliptic_curves = GetNullableObjectField(
+ jni, j_ice_server, j_ice_server_tls_elliptic_curves_id);
PeerConnectionInterface::IceServer server;
server.uri = JavaToStdString(jni, uri);
server.username = JavaToStdString(jni, username);
@@ -383,6 +387,8 @@
server.tls_cert_policy = tls_cert_policy;
server.hostname = JavaToStdString(jni, hostname);
server.tls_alpn_protocols = JavaToStdVectorStrings(jni, tls_alpn_protocols);
+ server.tls_elliptic_curves =
+ JavaToStdVectorStrings(jni, tls_elliptic_curves);
ice_servers->push_back(server);
}
}
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm
index a28e237..eeb1177 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm
@@ -20,6 +20,7 @@
@synthesize tlsCertPolicy = _tlsCertPolicy;
@synthesize hostname = _hostname;
@synthesize tlsAlpnProtocols = _tlsAlpnProtocols;
+@synthesize tlsEllipticCurves = _tlsEllipticCurves;
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings {
return [self initWithURLStrings:urlStrings
@@ -57,7 +58,7 @@
credential:credential
tlsCertPolicy:tlsCertPolicy
hostname:hostname
- tlsAlpnProtocols:[NSMutableArray new]];
+ tlsAlpnProtocols:[NSArray array]];
}
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
@@ -66,6 +67,22 @@
tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy
hostname:(NSString *)hostname
tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols {
+ return [self initWithURLStrings:urlStrings
+ username:username
+ credential:credential
+ tlsCertPolicy:tlsCertPolicy
+ hostname:hostname
+ tlsAlpnProtocols:tlsAlpnProtocols
+ tlsEllipticCurves:[NSArray array]];
+}
+
+- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
+ username:(NSString *)username
+ credential:(NSString *)credential
+ tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy
+ hostname:(NSString *)hostname
+ tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols
+ tlsEllipticCurves:(NSArray<NSString *> *)tlsEllipticCurves {
NSParameterAssert(urlStrings.count);
if (self = [super init]) {
_urlStrings = [[NSArray alloc] initWithArray:urlStrings copyItems:YES];
@@ -74,18 +91,20 @@
_tlsCertPolicy = tlsCertPolicy;
_hostname = [hostname copy];
_tlsAlpnProtocols = [[NSArray alloc] initWithArray:tlsAlpnProtocols copyItems:YES];
+ _tlsEllipticCurves = [[NSArray alloc] initWithArray:tlsEllipticCurves copyItems:YES];
}
return self;
}
- (NSString *)description {
- return [NSString stringWithFormat:@"RTCIceServer:\n%@\n%@\n%@\n%@\n%@\n%@",
+ return [NSString stringWithFormat:@"RTCIceServer:\n%@\n%@\n%@\n%@\n%@\n%@\n%@",
_urlStrings,
_username,
_credential,
[self stringForTlsCertPolicy:_tlsCertPolicy],
_hostname,
- _tlsAlpnProtocols];
+ _tlsAlpnProtocols,
+ _tlsEllipticCurves];
}
#pragma mark - Private
@@ -110,6 +129,10 @@
iceServer.tls_alpn_protocols.push_back(proto.stdString);
}];
+ [_tlsEllipticCurves enumerateObjectsUsingBlock:^(NSString *curve, NSUInteger idx, BOOL *stop) {
+ iceServer.tls_elliptic_curves.push_back(curve.stdString);
+ }];
+
[_urlStrings enumerateObjectsUsingBlock:^(NSString *url,
NSUInteger idx,
BOOL *stop) {
@@ -144,6 +167,11 @@
for (auto const &proto : nativeServer.tls_alpn_protocols) {
[tlsAlpnProtocols addObject:[NSString stringForStdString:proto]];
}
+ NSMutableArray *tlsEllipticCurves =
+ [NSMutableArray arrayWithCapacity:nativeServer.tls_elliptic_curves.size()];
+ for (auto const &curve : nativeServer.tls_elliptic_curves) {
+ [tlsEllipticCurves addObject:[NSString stringForStdString:curve]];
+ }
RTCTlsCertPolicy tlsCertPolicy;
switch (nativeServer.tls_cert_policy) {
@@ -160,7 +188,8 @@
credential:credential
tlsCertPolicy:tlsCertPolicy
hostname:hostname
- tlsAlpnProtocols:tlsAlpnProtocols];
+ tlsAlpnProtocols:tlsAlpnProtocols
+ tlsEllipticCurves:tlsEllipticCurves];
return self;
}
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h b/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h
index e9baa8f..727da8a 100644
--- a/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h
@@ -46,6 +46,12 @@
/** List of protocols to be used in the TLS ALPN extension. */
@property(nonatomic, readonly) NSArray<NSString *> *tlsAlpnProtocols;
+/**
+ List elliptic curves to be used in the TLS elliptic curves extension.
+ Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
+ */
+@property(nonatomic, readonly) NSArray<NSString *> *tlsEllipticCurves;
+
- (nonnull instancetype)init NS_UNAVAILABLE;
/** Convenience initializer for a server with no authentication (e.g. STUN). */
@@ -87,7 +93,20 @@
credential:(nullable NSString *)credential
tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy
hostname:(nullable NSString *)hostname
- tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols
+ tlsAlpnProtocols:(NSArray<NSString *> *)tlsAlpnProtocols;
+
+/**
+ * Initialize an RTCIceServer with its associated URLs, optional username,
+ * optional credential, TLS cert policy, hostname, ALPN protocols and
+ * elliptic curves.
+ */
+- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
+ username:(nullable NSString *)username
+ credential:(nullable NSString *)credential
+ tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy
+ hostname:(nullable NSString *)hostname
+ tlsAlpnProtocols:(nullable NSArray<NSString *> *)tlsAlpnProtocols
+ tlsEllipticCurves:(nullable NSArray<NSString *> *)tlsEllipticCurves
NS_DESIGNATED_INITIALIZER;
@end
diff --git a/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm b/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm
index 9d42c07..669ede6 100644
--- a/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm
+++ b/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm
@@ -92,6 +92,24 @@
EXPECT_EQ(2u, iceStruct.tls_alpn_protocols.size());
}
+- (void)testTlsEllipticCurves {
+ RTCIceServer *server = [[RTCIceServer alloc] initWithURLStrings:@[ @"turn1:turn1.example.net" ]
+ username:@"username"
+ credential:@"credential"
+ tlsCertPolicy:RTCTlsCertPolicySecure
+ hostname:@"hostname"
+ tlsAlpnProtocols:@[ @"proto1", @"proto2" ]
+ tlsEllipticCurves:@[ @"curve1", @"curve2" ]];
+ webrtc::PeerConnectionInterface::IceServer iceStruct = server.nativeServer;
+ EXPECT_EQ(1u, iceStruct.urls.size());
+ EXPECT_EQ("turn1:turn1.example.net", iceStruct.urls.front());
+ EXPECT_EQ("username", iceStruct.username);
+ EXPECT_EQ("credential", iceStruct.password);
+ EXPECT_EQ("hostname", iceStruct.hostname);
+ EXPECT_EQ(2u, iceStruct.tls_alpn_protocols.size());
+ EXPECT_EQ(2u, iceStruct.tls_elliptic_curves.size());
+}
+
- (void)testInitFromNativeServer {
webrtc::PeerConnectionInterface::IceServer nativeServer;
nativeServer.username = "username";
@@ -100,6 +118,8 @@
nativeServer.hostname = "hostname";
nativeServer.tls_alpn_protocols.push_back("proto1");
nativeServer.tls_alpn_protocols.push_back("proto2");
+ nativeServer.tls_elliptic_curves.push_back("curve1");
+ nativeServer.tls_elliptic_curves.push_back("curve2");
RTCIceServer *iceServer =
[[RTCIceServer alloc] initWithNativeServer:nativeServer];
@@ -110,6 +130,7 @@
EXPECT_EQ("password", [NSString stdStringForString:iceServer.credential]);
EXPECT_EQ("hostname", [NSString stdStringForString:iceServer.hostname]);
EXPECT_EQ(2u, iceServer.tlsAlpnProtocols.count);
+ EXPECT_EQ(2u, iceServer.tlsEllipticCurves.count);
}
@end