Adding flag to enable/disable use of SRTP_AES128_CM_SHA1_32 crypto suite.

This flag (added to CryptoOptions) will allow applications to opt-in to
use of this suite, before it's disabled by default later. See bug for
more details.

TBR=magjed@webrtc.org

Bug: webrtc:7670
Change-Id: I800bedd4b26d807b6b7ac66b505d419c3323e454
Reviewed-on: https://webrtc-review.googlesource.com/64390
Commit-Queue: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22586}
This commit is contained in:
Taylor Brandstetter
2018-03-23 11:50:16 -07:00
committed by Commit Bot
parent 767a2ced73
commit 5e55fe845e
8 changed files with 87 additions and 13 deletions

View File

@ -194,14 +194,17 @@ bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
return false;
}
// For audio, HMAC 32 is prefered over HMAC 80 because of the low overhead.
// For audio, HMAC 32 (if enabled) is prefered over HMAC 80 because of the
// low overhead.
void GetSupportedAudioSdesCryptoSuites(const rtc::CryptoOptions& crypto_options,
std::vector<int>* crypto_suites) {
if (crypto_options.enable_gcm_crypto_suites) {
crypto_suites->push_back(rtc::SRTP_AEAD_AES_256_GCM);
crypto_suites->push_back(rtc::SRTP_AEAD_AES_128_GCM);
}
crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_32);
if (crypto_options.enable_aes128_sha1_32_crypto_cipher) {
crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_32);
}
crypto_suites->push_back(rtc::SRTP_AES128_CM_SHA1_80);
}
@ -245,8 +248,8 @@ void GetSupportedDataSdesCryptoSuiteNames(
}
// Support any GCM cipher (if enabled through options). For video support only
// 80-bit SHA1 HMAC. For audio 32-bit HMAC is tolerated unless bundle is enabled
// because it is low overhead.
// 80-bit SHA1 HMAC. For audio 32-bit HMAC is tolerated (if enabled) unless
// bundle is enabled because it is low overhead.
// Pick the crypto in the list that is supported.
static bool SelectCrypto(const MediaContentDescription* offer,
bool bundle,
@ -261,7 +264,7 @@ static bool SelectCrypto(const MediaContentDescription* offer,
rtc::IsGcmCryptoSuiteName(i->cipher_suite)) ||
rtc::CS_AES_CM_128_HMAC_SHA1_80 == i->cipher_suite ||
(rtc::CS_AES_CM_128_HMAC_SHA1_32 == i->cipher_suite && audio &&
!bundle)) {
!bundle && crypto_options.enable_aes128_sha1_32_crypto_cipher)) {
return CreateCryptoParams(i->tag, i->cipher_suite, crypto);
}
}

View File

@ -1365,13 +1365,10 @@ class PeerConnectionIntegrationBaseTest : public testing::Test {
return expectations_correct;
}
void TestGcmNegotiationUsesCipherSuite(bool local_gcm_enabled,
bool remote_gcm_enabled,
int expected_cipher_suite) {
PeerConnectionFactory::Options caller_options;
caller_options.crypto_options.enable_gcm_crypto_suites = local_gcm_enabled;
PeerConnectionFactory::Options callee_options;
callee_options.crypto_options.enable_gcm_crypto_suites = remote_gcm_enabled;
void TestNegotiatedCipherSuite(
const PeerConnectionFactory::Options& caller_options,
const PeerConnectionFactory::Options& callee_options,
int expected_cipher_suite) {
ASSERT_TRUE(CreatePeerConnectionWrappersWithOptions(caller_options,
callee_options));
rtc::scoped_refptr<webrtc::FakeMetricsObserver> caller_observer =
@ -1390,6 +1387,17 @@ class PeerConnectionIntegrationBaseTest : public testing::Test {
caller()->pc()->RegisterUMAObserver(nullptr);
}
void TestGcmNegotiationUsesCipherSuite(bool local_gcm_enabled,
bool remote_gcm_enabled,
int expected_cipher_suite) {
PeerConnectionFactory::Options caller_options;
caller_options.crypto_options.enable_gcm_crypto_suites = local_gcm_enabled;
PeerConnectionFactory::Options callee_options;
callee_options.crypto_options.enable_gcm_crypto_suites = remote_gcm_enabled;
TestNegotiatedCipherSuite(caller_options, callee_options,
expected_cipher_suite);
}
protected:
const SdpSemantics sdp_semantics_;
@ -2600,6 +2608,40 @@ TEST_P(PeerConnectionIntegrationTest, CallerDtls10ToCalleeDtls12) {
ASSERT_TRUE(ExpectNewFrames(media_expectations));
}
// The three tests below verify that "enable_aes128_sha1_32_crypto_cipher"
// works as expected; the cipher should only be used if enabled by both sides.
TEST_P(PeerConnectionIntegrationTest,
Aes128Sha1_32_CipherNotUsedWhenOnlyCallerSupported) {
PeerConnectionFactory::Options caller_options;
caller_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = true;
PeerConnectionFactory::Options callee_options;
callee_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = false;
int expected_cipher_suite = rtc::SRTP_AES128_CM_SHA1_80;
TestNegotiatedCipherSuite(caller_options, callee_options,
expected_cipher_suite);
}
TEST_P(PeerConnectionIntegrationTest,
Aes128Sha1_32_CipherNotUsedWhenOnlyCalleeSupported) {
PeerConnectionFactory::Options caller_options;
caller_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = false;
PeerConnectionFactory::Options callee_options;
callee_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = true;
int expected_cipher_suite = rtc::SRTP_AES128_CM_SHA1_80;
TestNegotiatedCipherSuite(caller_options, callee_options,
expected_cipher_suite);
}
TEST_P(PeerConnectionIntegrationTest, Aes128Sha1_32_CipherUsedWhenSupported) {
PeerConnectionFactory::Options caller_options;
caller_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = true;
PeerConnectionFactory::Options callee_options;
callee_options.crypto_options.enable_aes128_sha1_32_crypto_cipher = true;
int expected_cipher_suite = rtc::SRTP_AES128_CM_SHA1_32;
TestNegotiatedCipherSuite(caller_options, callee_options,
expected_cipher_suite);
}
// Test that a non-GCM cipher is used if both sides only support non-GCM.
TEST_P(PeerConnectionIntegrationTest, NonGcmCipherUsedWhenGcmNotSupported) {
bool local_gcm_enabled = false;

View File

@ -105,7 +105,11 @@ std::vector<int> GetSupportedDtlsSrtpCryptoSuites(
// Note: SRTP_AES128_CM_SHA1_80 is what is required to be supported (by
// draft-ietf-rtcweb-security-arch), but SRTP_AES128_CM_SHA1_32 is allowed as
// well, and saves a few bytes per packet if it ends up selected.
crypto_suites.push_back(rtc::SRTP_AES128_CM_SHA1_32);
// As the cipher suite is potentially insecure, it will only be used if
// enabled by both peers.
if (crypto_options.enable_aes128_sha1_32_crypto_cipher) {
crypto_suites.push_back(rtc::SRTP_AES128_CM_SHA1_32);
}
crypto_suites.push_back(rtc::SRTP_AES128_CM_SHA1_80);
return crypto_suites;
}

View File

@ -80,6 +80,15 @@ struct CryptoOptions {
// if both sides enable it.
bool enable_gcm_crypto_suites = false;
// If set to true, the (potentially insecure) crypto cipher
// SRTP_AES128_CM_SHA1_32 will be included in the list of supported ciphers
// during negotiation. It will only be used if both peers support it and no
// other ciphers get preferred.
// TODO(crbug.com/webrtc/7670): Change default to false after sending PSA and
// giving time for users to set this flag to true explicitly, if they still
// want to use this crypto suite.
bool enable_aes128_sha1_32_crypto_cipher = true;
// If set to true, encrypted RTP header extensions as defined in RFC 6904
// will be negotiated. They will only be used if both peers support them.
bool enable_encrypted_rtp_header_extensions = false;

View File

@ -107,6 +107,7 @@ public class PeerConnectionFactory {
public int networkIgnoreMask;
public boolean disableEncryption;
public boolean disableNetworkMonitor;
public boolean enableAes128Sha1_32CryptoCipher;
@CalledByNative("Options")
int getNetworkIgnoreMask() {
@ -122,6 +123,11 @@ public class PeerConnectionFactory {
boolean getDisableNetworkMonitor() {
return disableNetworkMonitor;
}
@CalledByNative("Options")
boolean getEnableAes128Sha1_32CryptoCipher() {
return enableAes128Sha1_32CryptoCipher;
}
}
public static class Builder {

View File

@ -52,6 +52,8 @@ JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni,
bool disable_encryption = Java_Options_getDisableEncryption(jni, options);
bool disable_network_monitor =
Java_Options_getDisableNetworkMonitor(jni, options);
bool enable_aes128_sha1_32_crypto_cipher =
Java_Options_getEnableAes128Sha1_32CryptoCipher(jni, options);
PeerConnectionFactoryInterface::Options native_options;
@ -60,6 +62,9 @@ JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni,
native_options.network_ignore_mask = network_ignore_mask;
native_options.disable_encryption = disable_encryption;
native_options.disable_network_monitor = disable_network_monitor;
native_options.crypto_options.enable_aes128_sha1_32_crypto_cipher =
enable_aes128_sha1_32_crypto_cipher;
return native_options;
}
} // namespace

View File

@ -34,6 +34,7 @@ void setNetworkBit(webrtc::PeerConnectionFactoryInterface::Options* options,
@synthesize ignoreCellularNetworkAdapter = _ignoreCellularNetworkAdapter;
@synthesize ignoreWiFiNetworkAdapter = _ignoreWiFiNetworkAdapter;
@synthesize ignoreEthernetNetworkAdapter = _ignoreEthernetNetworkAdapter;
@synthesize enableAes128Sha1_32CryptoCipher = _enableAes128Sha1_32CryptoCipher;
- (instancetype)init {
return [super init];
@ -50,6 +51,8 @@ void setNetworkBit(webrtc::PeerConnectionFactoryInterface::Options* options,
setNetworkBit(&options, rtc::ADAPTER_TYPE_WIFI, self.ignoreWiFiNetworkAdapter);
setNetworkBit(&options, rtc::ADAPTER_TYPE_ETHERNET, self.ignoreEthernetNetworkAdapter);
options.crypto_options.enable_aes128_sha1_32_crypto_cipher = self.enableAes128Sha1_32CryptoCipher;
return options;
}

View File

@ -31,6 +31,8 @@ RTC_EXPORT
@property(nonatomic, assign) BOOL ignoreEthernetNetworkAdapter;
@property(nonatomic, assign) BOOL enableAes128Sha1_32CryptoCipher;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
@end