| <!doctype html> | |
| <meta charset=utf-8> | |
| <title>RTCPeerConnection.prototype.createOffer</title> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="../RTCPeerConnection-helper.js"></script> | |
| <script src="../RTCStats-helper.js"></script> | |
| <script> | |
| 'use strict'; | |
| // draft-ietf-rtcweb-security-20 section 6.5 | |
| // | |
| // All Implementations MUST support DTLS 1.2 with the | |
| // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher suite and the P-256 | |
| // curve [FIPS186]. | |
| // ....... The DTLS-SRTP protection profile | |
| // SRTP_AES128_CM_HMAC_SHA1_80 MUST be supported for SRTP. | |
| // Implementations MUST favor cipher suites which support (Perfect | |
| // Forward Secrecy) PFS over non-PFS cipher suites and SHOULD favor AEAD | |
| // over non-AEAD cipher suites. | |
| const acceptableTlsVersions = new Set([ | |
| 'FEFD', // DTLS 1.2 - RFC 6437 section 4.1 | |
| '0304', // TLS 1.3 - RFC 8446 section 5.1 | |
| ]); | |
| const acceptableDtlsCiphersuites = new Set([ | |
| 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', | |
| ]); | |
| const acceptableSrtpCiphersuites = new Set([ | |
| 'SRTP_AES128_CM_HMAC_SHA1_80', | |
| 'AES_CM_128_HMAC_SHA1_80', | |
| ]); | |
| const acceptableTlsGroups = new Set([ | |
| 'P-256', | |
| ]); | |
| const acceptableValues = { | |
| 'tlsVersion': acceptableTlsVersions, | |
| 'dtlsCipher': acceptableDtlsCiphersuites, | |
| 'srtpCipher': acceptableSrtpCiphersuites, | |
| 'tlsGroup': acceptableTlsGroups, | |
| }; | |
| function verifyStat(name, transportStats) { | |
| assert_not_equals(typeof transportStats, 'undefined'); | |
| assert_true(name in transportStats, 'Value present:'); | |
| assert_true(acceptableValues[name].has(transportStats[name])); | |
| } | |
| for (const name of Object.keys(acceptableValues)) { | |
| promise_test(async t => { | |
| const pc1 = new RTCPeerConnection(); | |
| const pc2 = new RTCPeerConnection(); | |
| t.add_cleanup(() => pc1.close()); | |
| t.add_cleanup(() => pc2.close()); | |
| pc1.createDataChannel('foo'); | |
| exchangeIceCandidates(pc1, pc2); | |
| await exchangeOfferAnswer(pc1, pc2); | |
| await waitForState(pc1.sctp.transport, 'connected'); | |
| const statsReport = await pc1.getStats(); | |
| const transportStats = findStatsFromReport(statsReport, | |
| stats => stats.type === 'transport') | |
| verifyStat(name, transportStats); | |
| }, name + ' is acceptable on data-only'); | |
| promise_test(async t => { | |
| const pc1 = new RTCPeerConnection(); | |
| const pc2 = new RTCPeerConnection(); | |
| t.add_cleanup(() => pc1.close()); | |
| t.add_cleanup(() => pc2.close()); | |
| const transceiver = pc1.addTransceiver('video'); | |
| exchangeIceCandidates(pc1, pc2); | |
| await exchangeOfferAnswer(pc1, pc2); | |
| await waitForState(transceiver.sender.transport, 'connected'); | |
| const statsReport = await pc1.getStats(); | |
| const transportStats = findStatsFromReport(statsReport, | |
| stats => stats.type === 'transport') | |
| verifyStat(name, transportStats); | |
| }, name + ' is acceptable on video-only'); | |
| } | |
| </script> |