Example #1
0
        /// <summary>
        /// Regardless of the encryption or message authentication transform that
        /// is employed (it may be an SRTP pre-defined transform or newly
        /// introduced according to Section 6), interoperable SRTP
        /// implementations MUST use the SRTP key derivation to generate session
        /// keys.  Once the key derivation rate is properly signaled at the start
        /// of the session, there is no need for extra communication between the
        /// parties that use SRTP key derivation.
        ///
        /// https://tools.ietf.org/html/rfc3711#section-4.3
        /// </summary>
        private void DeriveKeys(SrtpStreamContext srtpStreamContext, int packetIndex, byte[] masterKey, byte[] masterSalt)
        {
            /*
             * At least one initial key derivation SHALL be performed by SRTP, i.e.,
             * the first key derivation is REQUIRED.  Further applications of the
             * key derivation MAY be performed, according to the
             * "key_derivation_rate" value in the cryptographic context.  The key
             * derivation function SHALL initially be invoked before the first
             * packet and then, when r > 0, a key derivation is performed whenever
             * index mod r equals zero.  This can be thought of as "refreshing" the
             * session keys.  The value of "key_derivation_rate" MUST be kept fixed
             * for the lifetime of the associated master key.
             */
            /*
             * Let "a DIV t" denote integer division of a by t, rounded down, and
             * with the convention that "a DIV 0 = 0" for all a.  We also make the
             * convention of treating "a DIV t" as a bit string of the same length
             * as a, and thus "a DIV t" will in general have leading zeros.
             *
             * Let r = index DIV key_derivation_rate (with DIV as defined above).
             */

            var kdr = srtpStreamContext.KeyDerivationRate;

            var r = (uint)(kdr == 0 ? 0 : packetIndex / kdr);

            var shouldDeriveKeys = srtpStreamContext.DerivedKeys is null || r > 0 && packetIndex % r == 0;

            if (!shouldDeriveKeys)
            {
                return;
            }

            var derivedKeys = new SrtpDerivedkeys();

            derivedKeys.SessionKey = DeriveKey(masterKey, masterSalt, r, SrtpEncryptionKeyLabel.SrtpEncryptionKey, SrtpConstants.SrtpDefaultEncryptionSessionKeyLength);

            derivedKeys.AuthKey = DeriveKey(masterKey, masterSalt, r, SrtpEncryptionKeyLabel.SrtpMessageAuthenticationKey, SrtpConstants.SrtpDefaultAuthSessionKeyLength);

            derivedKeys.CipherSalt = DeriveKey(masterKey, masterSalt, r, SrtpEncryptionKeyLabel.SrtpSaltingKey, SrtpConstants.SrtpDefaultSaltSessionKeyLength);

            srtpStreamContext.DerivedKeys = derivedKeys;
        }
Example #2
0
        private static byte[] EncryptPayloadWithAesCtrMode(SrtpDerivedkeys derivedKeys, uint ssrc, byte[] rtpBody, int packetIndex)
        {
            var sessionKey = derivedKeys.SessionKey;
            var cipherSalt = derivedKeys.CipherSalt;

            // where the 128-bit integer value IV SHALL be defined by the SSRC, the
            // SRTP packet index i, and the SRTP session salting key k_s, as below.
            //
            //  IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)

            var iv =
                cipherSalt.ShiftLeft(16)
                .Xor(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(ssrc)).ShiftLeft(64))
                .Xor(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(packetIndex)).ShiftLeft(16));

            var encrypted = AesCounterMode.Encrypt(sessionKey, iv, rtpBody);

            return(encrypted);
        }