Example #1
0
        public DtlsSrtpClient(Certificate certificateChain, AsymmetricKeyParameter privateKey,
                              UseSrtpData clientSrtpData)
        {
            if (certificateChain == null && privateKey == null)
            {
                (certificateChain, privateKey) = DtlsUtils.CreateSelfSignedTlsCert();
            }

            if (clientSrtpData == null)
            {
                SecureRandom random             = new SecureRandom();
                int[]        protectionProfiles = { SrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80 };
                byte[]       mki = new byte[(SrtpParameters.SRTP_AES128_CM_HMAC_SHA1_80.GetCipherKeyLength() +
                                             SrtpParameters.SRTP_AES128_CM_HMAC_SHA1_80.GetCipherSaltLength()) / 8];
                random.NextBytes(mki); // Reusing our secure random for generating the key.
                this.clientSrtpData = new UseSrtpData(protectionProfiles, mki);
            }
            else
            {
                this.clientSrtpData = clientSrtpData;
            }

            this.mPrivateKey  = privateKey;
            mCertificateChain = certificateChain;

            //Generate FingerPrint
            var certificate = mCertificateChain.GetCertificateAt(0);

            Fingerprint = certificate != null?DtlsUtils.Fingerprint(certificate) : null;
        }
Example #2
0
        protected override TlsSignerCredentials GetRsaSignerCredentials()
        {
            /*
             * TODO Note that this code fails to provide default value for the client supported
             * algorithms if it wasn't sent.
             */
            SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
            IList sigAlgs = mSupportedSignatureAlgorithms;

            if (sigAlgs != null)
            {
                foreach (var sigAlgUncasted in sigAlgs)
                {
                    SignatureAndHashAlgorithm sigAlg = sigAlgUncasted as SignatureAndHashAlgorithm;
                    if (sigAlg != null && sigAlg.Signature == SignatureAlgorithm.rsa)
                    {
                        signatureAndHashAlgorithm = sigAlg;
                        break;
                    }
                }

                if (signatureAndHashAlgorithm == null)
                {
                    return(null);
                }
            }
            return(DtlsUtils.LoadSignerCredentials(mContext, mCertificateChain, mPrivateKey, signatureAndHashAlgorithm));
        }
        public DtlsSrtpServer(Certificate certificateChain, AsymmetricKeyParameter privateKey)
        {
            this.cipherSuites = base.GetCipherSuites();

            this.mPrivateKey  = privateKey;
            mCertificateChain = certificateChain;

            //Generate FingerPrint
            var certificate = mCertificateChain.GetCertificateAt(0);

            this.mFingerPrint = certificate != null?DtlsUtils.Fingerprint(certificate) : null;
        }
Example #4
0
        public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
        {
            byte[] certificateTypes = certificateRequest.CertificateTypes;
            if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
            {
                return(null);
            }

            return(DtlsUtils.LoadSignerCredentials(mContext,
                                                   certificateRequest.SupportedSignatureAlgorithms,
                                                   SignatureAlgorithm.rsa,
                                                   mClient.mCertificateChain,
                                                   mClient.mPrivateKey));
        }
Example #5
0
        public DtlsSrtpServer(Certificate certificateChain, AsymmetricKeyParameter privateKey)
        {
            if (certificateChain == null && privateKey == null)
            {
                (certificateChain, privateKey) = DtlsUtils.CreateSelfSignedTlsCert();
            }

            this.cipherSuites = base.GetCipherSuites();

            this.mPrivateKey  = privateKey;
            mCertificateChain = certificateChain;

            //Generate FingerPrint
            var certificate = mCertificateChain.GetCertificateAt(0);

            this.mFingerPrint = certificate != null?DtlsUtils.Fingerprint(certificate) : null;
        }
Example #6
0
        /// <summary>
        ///  DtlsHandshake requires DtlsSrtpTransport to work.
        ///  DtlsSrtpTransport is similar to C++ DTLS class combined with Srtp class and can perform
        ///  Handshake as Server or Client in same call. The constructor of transport require a DtlsStrpClient
        ///  or DtlsSrtpServer to work.
        /// </summary>
        /// <param name="dtlsHandle">The DTLS transport handle to perform the handshake with.</param>
        /// <returns></returns>
        private bool DoDtlsHandshake(DtlsSrtpTransport dtlsHandle)
        {
            logger.LogDebug("RTCPeerConnection DoDtlsHandshake started.");

            var rtpChannel = GetRtpChannel(SDPMediaTypesEnum.audio);

            dtlsHandle.OnDataReady += (buf) =>
            {
                //logger.LogDebug($"DTLS transport sending {buf.Length} bytes to {AudioDestinationEndPoint}.");
                rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, AudioDestinationEndPoint, buf);
            };

            var handshakeResult = dtlsHandle.DoHandshake();

            if (!handshakeResult)
            {
                logger.LogWarning($"RTCPeerConnection DTLS handshake failed.");
                return(false);
            }
            else
            {
                logger.LogDebug($"RTCPeerConnection DTLS handshake result {handshakeResult}, is handshake complete {dtlsHandle.IsHandshakeComplete()}.");

                var expectedFp        = RemotePeerDtlsFingerprint;
                var remoteFingerprint = DtlsUtils.Fingerprint(expectedFp.algorithm, dtlsHandle.GetRemoteCertificate().GetCertificateAt(0));

                if (remoteFingerprint.value != expectedFp.value)
                {
                    logger.LogWarning($"RTCPeerConnection remote certificate fingerprint mismatch, expected {expectedFp}, actual {remoteFingerprint}.");
                    return(false);
                }
                else
                {
                    logger.LogDebug($"RTCPeerConnection remote certificate fingerprint matched expected value of {remoteFingerprint.value} for {remoteFingerprint.algorithm}.");

                    base.SetSecurityContext(
                        dtlsHandle.ProtectRTP,
                        dtlsHandle.UnprotectRTP,
                        dtlsHandle.ProtectRTCP,
                        dtlsHandle.UnprotectRTCP);

                    return(true);
                }
            }
        }
        /// <summary>
        /// Attempts to parse the fingerprint fields from a string.
        /// </summary>
        /// <param name="str">The string to parse from.</param>
        /// <param name="fingerprint">If successful a fingerprint object.</param>
        /// <returns>True if a fingerprint was successfully parsed. False if not.</returns>
        public static bool TryParse(string str, out RTCDtlsFingerprint fingerprint)
        {
            fingerprint = null;

            if (string.IsNullOrEmpty(str))
            {
                return(false);
            }
            else
            {
                int spaceIndex = str.IndexOf(' ');
                if (spaceIndex == -1)
                {
                    return(false);
                }
                else
                {
                    string algStr = str.Substring(0, spaceIndex);
                    string val    = str.Substring(spaceIndex + 1);

                    if (!DtlsUtils.IsHashSupported(algStr))
                    {
                        return(false);
                    }
                    else
                    {
                        fingerprint = new RTCDtlsFingerprint
                        {
                            algorithm = algStr,
                            value     = val
                        };
                        return(true);
                    }
                }
            }
        }
Example #8
0
 public DtlsSrtpClient(string[] certificatesPath, string keyPath) :
     this(DtlsUtils.LoadCertificateChain(certificatesPath), DtlsUtils.LoadPrivateKeyResource(keyPath))
 {
 }
Example #9
0
 public DtlsSrtpClient(X509Certificate2 certificate) :
     this(DtlsUtils.LoadCertificateChain(certificate), DtlsUtils.LoadPrivateKeyResource(certificate))
 {
 }
Example #10
0
 protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
 {
     return(DtlsUtils.LoadEncryptionCredentials(mContext, mCertificateChain, mPrivateKey));
 }
Example #11
0
 protected override TlsSignerCredentials GetECDsaSignerCredentials()
 {
     return(DtlsUtils.LoadSignerCredentials(mContext, mCertificateChain, mPrivateKey, new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa)));
 }
 public List <RTCDtlsFingerprint> getFingerprints()
 {
     return(new List <RTCDtlsFingerprint> {
         DtlsUtils.Fingerprint(Certificate)
     });
 }
Example #13
0
 public DtlsSrtpClient(UseSrtpData clientSrtpData) : this(DtlsUtils.CreateSelfSignedCert())
 {
     this.clientSrtpData = clientSrtpData;
 }
Example #14
0
 public DtlsSrtpClient() :
     this(DtlsUtils.CreateSelfSignedCert())
 {
 }
 public DtlsSrtpServer() : this(DtlsUtils.CreateSelfSignedCert())
 {
 }
Example #16
0
 public DtlsSrtpServer(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) : this(DtlsUtils.LoadCertificateChain(certificate), DtlsUtils.LoadPrivateKeyResource(certificate))
 {
 }
Example #17
0
        /// <summary>
        /// Constructor to create a new RTC peer connection instance.
        /// </summary>
        /// <param name="configuration">Optional.</param>
        public RTCPeerConnection(RTCConfiguration configuration) :
            base(true, true, true, configuration?.X_BindAddress)
        {
            if (_configuration != null &&
                _configuration.iceTransportPolicy == RTCIceTransportPolicy.relay &&
                _configuration.iceServers?.Count == 0)
            {
                throw new ApplicationException("RTCPeerConnection must have at least one ICE server specified for a relay only transport policy.");
            }

            if (configuration != null)
            {
                _configuration = configuration;
                if (_configuration.certificates?.Count > 0)
                {
                    // Find the first certificate that has a usable private key.
                    RTCCertificate usableCert = null;
                    foreach (var cert in _configuration.certificates)
                    {
                        // Attempting to check that a certificate has an exportable private key.
                        // TODO: Does not seem to be a particularly reliable way of checking private key exportability.
                        if (cert.Certificate.HasPrivateKey)
                        {
                            //if (cert.Certificate.PrivateKey is RSACryptoServiceProvider)
                            //{
                            //    var rsa = cert.Certificate.PrivateKey as RSACryptoServiceProvider;
                            //    if (!rsa.CspKeyContainerInfo.Exportable)
                            //    {
                            //        logger.LogWarning($"RTCPeerConnection was passed a certificate for {cert.Certificate.FriendlyName} with a non-exportable RSA private key.");
                            //    }
                            //    else
                            //    {
                            //        usableCert = cert;
                            //        break;
                            //    }
                            //}
                            //else
                            //{
                            usableCert = cert;
                            break;
                            //}
                        }
                    }

                    if (usableCert == null)
                    {
                        throw new ApplicationException("RTCPeerConnection was not able to find a certificate from the input configuration list with a usable private key.");
                    }
                    else
                    {
                        _currentCertificate = usableCert;
                    }
                }

                if (_configuration.X_UseRtpFeedbackProfile)
                {
                    RTP_MEDIA_PROFILE = RTP_MEDIA_FEEDBACK_PROFILE;
                }
            }
            else
            {
                _configuration = new RTCConfiguration();
            }

            // No certificate was provided so create a new self signed one.
            if (_configuration.certificates == null || _configuration.certificates.Count == 0)
            {
                _currentCertificate = new RTCCertificate {
                    Certificate = DtlsUtils.CreateSelfSignedCert()
                };
                _configuration.certificates = new List <RTCCertificate> {
                    _currentCertificate
                };
            }

            SessionID         = Guid.NewGuid().ToString();
            LocalSdpSessionID = Crypto.GetRandomInt(5).ToString();

            // Request the underlying RTP session to create a single RTP channel that will
            // be used to multiplex all required media streams.
            addSingleTrack();

            _rtpIceChannel = GetRtpChannel();

            _rtpIceChannel.OnIceCandidate             += (candidate) => onicecandidate?.Invoke(candidate);
            _rtpIceChannel.OnIceConnectionStateChange += (state) =>
            {
                if (state == RTCIceConnectionState.connected && _rtpIceChannel.NominatedEntry != null)
                {
                    var connectedEP = _rtpIceChannel.NominatedEntry.RemoteCandidate.DestinationEndPoint;
                    base.SetDestination(SDPMediaTypesEnum.audio, connectedEP, connectedEP);

                    logger.LogInformation($"ICE connected to remote end point {AudioDestinationEndPoint}.");

                    DtlsSrtpTransport dtlsHandle = new DtlsSrtpTransport(
                        IceRole == IceRolesEnum.active ?
                        (IDtlsSrtpPeer) new DtlsSrtpClient(_currentCertificate.Certificate) :
                        (IDtlsSrtpPeer) new DtlsSrtpServer(_currentCertificate.Certificate));

                    OnDtlsPacket += (buf) =>
                    {
                        logger.LogDebug($"DTLS transport received {buf.Length} bytes from {AudioDestinationEndPoint}.");
                        dtlsHandle.WriteToRecvStream(buf);
                    };

                    logger.LogDebug($"Starting DLS handshake with role {IceRole}.");
                    Task.Run <bool>(() => DoDtlsHandshake(dtlsHandle))
                    .ContinueWith(t =>
                    {
                        if (t.IsFaulted)
                        {
                            logger.LogWarning($"RTCPeerConnection DTLS handshake task completed in a faulted state. {t.Exception?.Flatten().Message}");

                            connectionState = RTCPeerConnectionState.failed;
                            onconnectionstatechange?.Invoke(connectionState);
                        }
                        else
                        {
                            connectionState = (t.Result) ? RTCPeerConnectionState.connected : connectionState = RTCPeerConnectionState.failed;
                            onconnectionstatechange?.Invoke(connectionState);
                        }
                    });
                }

                iceConnectionState = state;
                oniceconnectionstatechange?.Invoke(iceConnectionState);
            };
            _rtpIceChannel.OnIceGatheringStateChange += (state) => onicegatheringstatechange?.Invoke(state);
            _rtpIceChannel.OnIceCandidateError       += (candidate, error) => onicecandidateerror?.Invoke(candidate, error);

            OnRtpClosed += Close;
            OnRtcpBye   += Close;

            onnegotiationneeded?.Invoke();

            _rtpIceChannel.StartGathering();
        }