diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index 6a2b904453..e23b70592f 100644 --- a/webrtc/api/peerconnectioninterface.h +++ b/webrtc/api/peerconnectioninterface.h @@ -195,12 +195,15 @@ class PeerConnectionInterface : public rtc::RefCountInterface { std::string hostname; // List of protocols to be used in the TLS ALPN extension. std::vector tls_alpn_protocols; + // List of elliptic curves to be used in the TLS elliptic curves extension. + std::vector 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/webrtc/p2p/base/basicpacketsocketfactory.cc b/webrtc/p2p/base/basicpacketsocketfactory.cc index fe9eb4bd93..b0f464b494 100644 --- a/webrtc/p2p/base/basicpacketsocketfactory.cc +++ b/webrtc/p2p/base/basicpacketsocketfactory.cc @@ -159,6 +159,7 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket( } ssl_adapter->SetAlpnProtocols(tcp_options.tls_alpn_protocols); + ssl_adapter->SetEllipticCurves(tcp_options.tls_elliptic_curves); socket = ssl_adapter; diff --git a/webrtc/p2p/base/packetsocketfactory.h b/webrtc/p2p/base/packetsocketfactory.h index 34f568c708..8ae0bd3319 100644 --- a/webrtc/p2p/base/packetsocketfactory.h +++ b/webrtc/p2p/base/packetsocketfactory.h @@ -20,6 +20,7 @@ namespace rtc { struct PacketSocketTcpOptions { int opts; std::vector tls_alpn_protocols; + std::vector tls_elliptic_curves; }; class AsyncPacketSocket; diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc index 0a5360991b..f47751fb08 100644 --- a/webrtc/p2p/base/port_unittest.cc +++ b/webrtc/p2p/base/port_unittest.cc @@ -536,7 +536,7 @@ class PortTest : public testing::Test, public sigslot::has_slots<> { 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::vector(), std::vector()); } RelayPort* CreateGturnPort(const SocketAddress& addr, ProtocolType int_proto, ProtocolType ext_proto) { diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h index eef4305591..63d7c71325 100644 --- a/webrtc/p2p/base/portallocator.h +++ b/webrtc/p2p/base/portallocator.h @@ -192,6 +192,7 @@ struct RelayServerConfig { int priority = 0; TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE; std::vector tls_alpn_protocols; + std::vector tls_elliptic_curves; }; class PortAllocatorSession : public sigslot::has_slots<> { diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc index 68dae82583..71a0311d2a 100644 --- a/webrtc/p2p/base/turnport.cc +++ b/webrtc/p2p/base/turnport.cc @@ -222,7 +222,8 @@ TurnPort::TurnPort(rtc::Thread* thread, const RelayCredentials& credentials, int server_priority, const std::string& origin, - const std::vector& tls_alpn_protocols) + const std::vector& tls_alpn_protocols, + const std::vector& tls_elliptic_curves) : Port(thread, RELAY_PORT_TYPE, factory, @@ -233,6 +234,7 @@ TurnPort::TurnPort(rtc::Thread* thread, 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 @@ bool TurnPort::CreateTurnClientSocket() { 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/webrtc/p2p/base/turnport.h b/webrtc/p2p/base/turnport.h index 46200a988c..4d9a811644 100644 --- a/webrtc/p2p/base/turnport.h +++ b/webrtc/p2p/base/turnport.h @@ -70,10 +70,11 @@ class TurnPort : public Port { const RelayCredentials& credentials, int server_priority, const std::string& origin, - const std::vector& tls_alpn_protocols) { + const std::vector& tls_alpn_protocols, + const std::vector& 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 @@ class TurnPort : public Port { return tls_alpn_protocols_; } + virtual std::vector GetTlsEllipticCurves() const { + return tls_elliptic_curves_; + } + virtual void PrepareAddress(); virtual Connection* CreateConnection( const Candidate& c, PortInterface::CandidateOrigin origin); @@ -192,7 +197,8 @@ class TurnPort : public Port { const RelayCredentials& credentials, int server_priority, const std::string& origin, - const std::vector& alpn_protocols); + const std::vector& tls_alpn_protocols, + const std::vector& tls_elliptic_curves); private: enum { @@ -273,6 +279,7 @@ class TurnPort : public Port { ProtocolAddress server_address_; TlsCertPolicy tls_cert_policy_ = TlsCertPolicy::TLS_CERT_POLICY_SECURE; std::vector tls_alpn_protocols_; + std::vector tls_elliptic_curves_; RelayCredentials credentials_; AttemptedServerSet attempted_server_addresses_; diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc index 546c21e782..a8e2937ce4 100644 --- a/webrtc/p2p/base/turnport_unittest.cc +++ b/webrtc/p2p/base/turnport_unittest.cc @@ -263,7 +263,8 @@ class TurnPortTest : public testing::Test, RelayCredentials credentials(username, password); turn_port_.reset(TurnPort::Create( &main_, &socket_factory_, network, 0, 0, kIceUfrag1, kIcePwd1, - server_address, credentials, 0, origin, std::vector())); + server_address, credentials, 0, origin, std::vector(), + std::vector())); // This TURN port will be the controlling. turn_port_->SetIceRole(ICEROLE_CONTROLLING); ConnectSignals(); diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc index fe2dfb6d1e..992aee6acc 100644 --- a/webrtc/p2p/client/basicportallocator.cc +++ b/webrtc/p2p/client/basicportallocator.cc @@ -1445,7 +1445,7 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) { 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/webrtc/pc/iceserverparsing.cc b/webrtc/pc/iceserverparsing.cc index 00e9f2590f..9b802fc591 100644 --- a/webrtc/pc/iceserverparsing.cc +++ b/webrtc/pc/iceserverparsing.cc @@ -258,6 +258,7 @@ static RTCErrorType ParseIceServerUrl( 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/webrtc/rtc_base/openssladapter.cc b/webrtc/rtc_base/openssladapter.cc index 9164258692..d944fa04a5 100644 --- a/webrtc/rtc_base/openssladapter.cc +++ b/webrtc/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 @@ void OpenSSLAdapter::SetAlpnProtocols(const std::vector& protos) { alpn_protocols_ = protos; } +void OpenSSLAdapter::SetEllipticCurves(const std::vector& curves) { + elliptic_curves_ = curves; +} + void OpenSSLAdapter::SetMode(SSLMode mode) { RTC_DCHECK(!ssl_ctx_); RTC_DCHECK(state_ == SSL_NONE); @@ -445,6 +450,10 @@ int OpenSSLAdapter::BeginSSL() { } } + 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/webrtc/rtc_base/openssladapter.h b/webrtc/rtc_base/openssladapter.h index 9c6c34479b..6409c76a49 100644 --- a/webrtc/rtc_base/openssladapter.h +++ b/webrtc/rtc_base/openssladapter.h @@ -40,6 +40,7 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler { void SetIgnoreBadCert(bool ignore) override; void SetAlpnProtocols(const std::vector& protos) override; + void SetEllipticCurves(const std::vector& curves) override; void SetMode(SSLMode mode) override; void SetIdentity(SSLIdentity* identity) override; @@ -136,6 +137,8 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler { bool ignore_bad_cert_; // List of protocols to be used in the TLS ALPN extension. std::vector alpn_protocols_; + // List of elliptic curves to be used in the TLS elliptic curves extension. + std::vector elliptic_curves_; bool custom_verification_succeeded_; }; diff --git a/webrtc/rtc_base/ssladapter.h b/webrtc/rtc_base/ssladapter.h index b30e176c45..922f42e1d5 100644 --- a/webrtc/rtc_base/ssladapter.h +++ b/webrtc/rtc_base/ssladapter.h @@ -48,7 +48,9 @@ class SSLAdapter : public AsyncSocketAdapter { // 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& protos) = 0; + virtual void SetEllipticCurves(const std::vector& curves) = 0; // Do DTLS or TLS (default is TLS, if unspecified) virtual void SetMode(SSLMode mode) = 0; diff --git a/webrtc/rtc_base/ssladapter_unittest.cc b/webrtc/rtc_base/ssladapter_unittest.cc index 5c61f6a2f7..8e5d322b52 100644 --- a/webrtc/rtc_base/ssladapter_unittest.cc +++ b/webrtc/rtc_base/ssladapter_unittest.cc @@ -64,6 +64,10 @@ class SSLAdapterTestDummyClient : public sigslot::has_slots<> { ssl_adapter_->SetAlpnProtocols(protos); } + void SetEllipticCurves(const std::vector& curves) { + ssl_adapter_->SetEllipticCurves(curves); + } + rtc::SocketAddress GetAddress() const { return ssl_adapter_->GetLocalAddress(); } @@ -290,6 +294,10 @@ class SSLAdapterTestBase : public testing::Test, client_->SetAlpnProtocols(protos); } + void SetEllipticCurves(const std::vector& curves) { + client_->SetEllipticCurves(curves); + } + void TestHandshake(bool expect_success) { int rv; @@ -450,6 +458,14 @@ TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSALPN) { 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 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/webrtc/rtc_base/stringencode.cc b/webrtc/rtc_base/stringencode.cc index 93470b6d36..a4d594d88c 100644 --- a/webrtc/rtc_base/stringencode.cc +++ b/webrtc/rtc_base/stringencode.cc @@ -645,6 +645,28 @@ bool tokenize_first(const std::string& source, return true; } +std::string join(const std::vector& 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* fields) { RTC_DCHECK(fields); diff --git a/webrtc/rtc_base/stringencode.h b/webrtc/rtc_base/stringencode.h index 5296a9cbb0..a4452c2e97 100644 --- a/webrtc/rtc_base/stringencode.h +++ b/webrtc/rtc_base/stringencode.h @@ -136,6 +136,10 @@ inline std::string s_url_decode(const std::string& source) { 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& 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/webrtc/sdk/android/api/org/webrtc/PeerConnection.java b/webrtc/sdk/android/api/org/webrtc/PeerConnection.java index 8322410974..c362d92e2b 100644 --- a/webrtc/sdk/android/api/org/webrtc/PeerConnection.java +++ b/webrtc/sdk/android/api/org/webrtc/PeerConnection.java @@ -113,6 +113,10 @@ public class PeerConnection { // List of protocols to be used in the TLS ALPN extension. public final List 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 tlsEllipticCurves; + /** Convenience constructor for STUN servers. */ @Deprecated public IceServer(String uri) { @@ -132,22 +136,23 @@ public class PeerConnection { @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 tlsAlpnProtocols) { + String hostname, List tlsAlpnProtocols, List 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 @@ public class PeerConnection { private TlsCertPolicy tlsCertPolicy = TlsCertPolicy.TLS_CERT_POLICY_SECURE; private String hostname = ""; private List tlsAlpnProtocols; + private List tlsEllipticCurves; private Builder(String uri) { this.uri = uri; @@ -191,8 +197,14 @@ public class PeerConnection { return this; } + public Builder setTlsEllipticCurves(List 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/webrtc/sdk/android/src/jni/pc/java_native_conversion.cc b/webrtc/sdk/android/src/jni/pc/java_native_conversion.cc index 799f67dbce..eb9892ac65 100644 --- a/webrtc/sdk/android/src/jni/pc/java_native_conversion.cc +++ b/webrtc/sdk/android/src/jni/pc/java_native_conversion.cc @@ -364,6 +364,8 @@ void JavaToNativeIceServers(JNIEnv* jni, 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( GetObjectField(jni, j_ice_server, j_ice_server_uri_id)); jstring username = reinterpret_cast( @@ -376,6 +378,8 @@ void JavaToNativeIceServers(JNIEnv* jni, 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 @@ void JavaToNativeIceServers(JNIEnv* jni, 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/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm b/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm index a28e237623..eeb1177927 100644 --- a/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCIceServer.mm +++ b/webrtc/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 *)urlStrings { return [self initWithURLStrings:urlStrings @@ -57,7 +58,7 @@ credential:credential tlsCertPolicy:tlsCertPolicy hostname:hostname - tlsAlpnProtocols:[NSMutableArray new]]; + tlsAlpnProtocols:[NSArray array]]; } - (instancetype)initWithURLStrings:(NSArray *)urlStrings @@ -66,6 +67,22 @@ tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy hostname:(NSString *)hostname tlsAlpnProtocols:(NSArray *)tlsAlpnProtocols { + return [self initWithURLStrings:urlStrings + username:username + credential:credential + tlsCertPolicy:tlsCertPolicy + hostname:hostname + tlsAlpnProtocols:tlsAlpnProtocols + tlsEllipticCurves:[NSArray array]]; +} + +- (instancetype)initWithURLStrings:(NSArray *)urlStrings + username:(NSString *)username + credential:(NSString *)credential + tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy + hostname:(NSString *)hostname + tlsAlpnProtocols:(NSArray *)tlsAlpnProtocols + tlsEllipticCurves:(NSArray *)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/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h index e9baa8feb4..727da8acbe 100644 --- a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCIceServer.h @@ -46,6 +46,12 @@ RTC_EXPORT /** List of protocols to be used in the TLS ALPN extension. */ @property(nonatomic, readonly) NSArray *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 *tlsEllipticCurves; + - (nonnull instancetype)init NS_UNAVAILABLE; /** Convenience initializer for a server with no authentication (e.g. STUN). */ @@ -87,7 +93,20 @@ RTC_EXPORT credential:(nullable NSString *)credential tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy hostname:(nullable NSString *)hostname - tlsAlpnProtocols:(NSArray *)tlsAlpnProtocols + tlsAlpnProtocols:(NSArray *)tlsAlpnProtocols; + +/** + * Initialize an RTCIceServer with its associated URLs, optional username, + * optional credential, TLS cert policy, hostname, ALPN protocols and + * elliptic curves. + */ +- (instancetype)initWithURLStrings:(NSArray *)urlStrings + username:(nullable NSString *)username + credential:(nullable NSString *)credential + tlsCertPolicy:(RTCTlsCertPolicy)tlsCertPolicy + hostname:(nullable NSString *)hostname + tlsAlpnProtocols:(nullable NSArray *)tlsAlpnProtocols + tlsEllipticCurves:(nullable NSArray *)tlsEllipticCurves NS_DESIGNATED_INITIALIZER; @end diff --git a/webrtc/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm b/webrtc/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm index 9d42c0768d..669ede6908 100644 --- a/webrtc/sdk/objc/Framework/UnitTests/RTCIceServerTest.mm +++ b/webrtc/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