/** * Perform Counter Mode AES encryption / decryption * * @param pkt * the RTP packet to be encrypted / decrypted */ public void ProcessPacketAESCM(RawPacket pkt) { long ssrc = pkt.GetSSRC(); int seqNo = pkt.GetSequenceNumber(); #pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand long index = ((long)roc << 16) | seqNo; #pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand ivStore[0] = saltKey[0]; ivStore[1] = saltKey[1]; ivStore[2] = saltKey[2]; ivStore[3] = saltKey[3]; int i; for (i = 4; i < 8; i++) { ivStore[i] = (byte)((0xFF & (ssrc >> ((7 - i) * 8))) ^ this.saltKey[i]); } for (i = 8; i < 14; i++) { ivStore[i] = (byte)((0xFF & (byte)(index >> ((13 - i) * 8))) ^ this.saltKey[i]); } ivStore[14] = ivStore[15] = 0; int payloadOffset = pkt.GetHeaderLength(); int payloadLength = pkt.GetPayloadLength(); cipherCtr.Process(cipher, pkt.GetBuffer(), payloadOffset, payloadLength, ivStore); }
/** * Transform a RTP packet into a SRTP packet. This method is called when a * normal RTP packet ready to be sent. * * Operations done by the transformation may include: encryption, using * either Counter Mode encryption, or F8 Mode encryption, adding * authentication tag, currently HMC SHA1 method. * * Both encryption and authentication functionality can be turned off as * long as the SRTPPolicy used in this SRTPCryptoContext is requires no * encryption and no authentication. Then the packet will be sent out * untouched. However this is not encouraged. If no SRTP feature is enabled, * then we shall not use SRTP TransformConnector. We should use the original * method (RTPManager managed transportation) instead. * * @param pkt * the RTP packet that is going to be sent out */ public void TransformPacket(RawPacket pkt) { /* Encrypt the packet using Counter Mode encryption */ if (policy.EncType == SrtpPolicy.AESCM_ENCRYPTION || policy.EncType == SrtpPolicy.TWOFISH_ENCRYPTION) { ProcessPacketAESCM(pkt); } else if (policy.EncType == SrtpPolicy.AESF8_ENCRYPTION || policy.EncType == SrtpPolicy.TWOFISHF8_ENCRYPTION) { /* Encrypt the packet using F8 Mode encryption */ ProcessPacketAESF8(pkt); } /* Authenticate the packet */ if (policy.AuthType != SrtpPolicy.NULL_AUTHENTICATION) { AuthenticatePacketHMCSHA1(pkt, roc); pkt.Append(tagStore, policy.AuthTagLength); } /* Update the ROC if necessary */ int seqNo = pkt.GetSequenceNumber(); if (seqNo == 0xFFFF) { roc++; } }
/** * Transform a SRTP packet into a RTP packet. This method is called when a * SRTP packet is received. * * Operations done by the this operation include: Authentication check, * Packet replay check and Decryption. * * Both encryption and authentication functionality can be turned off as * long as the SRTPPolicy used in this SRTPCryptoContext requires no * encryption and no authentication. Then the packet will be sent out * untouched. However this is not encouraged. If no SRTP feature is enabled, * then we shall not use SRTP TransformConnector. We should use the original * method (RTPManager managed transportation) instead. * * @param pkt * the RTP packet that is just received * @return true if the packet can be accepted false if the packet failed * authentication or failed replay check */ public bool ReverseTransformPacket(RawPacket pkt) { int seqNo = pkt.GetSequenceNumber(); if (!seqNumSet) { seqNumSet = true; seqNum = seqNo; } // Guess the SRTP index (48 bit), see rFC 3711, 3.3.1 // Stores the guessed roc in this.guessedROC long guessedIndex = GuessIndex(seqNo); // Replay control if (!CheckReplay(seqNo, guessedIndex)) { return(false); } // Authenticate packet if (policy.AuthType != SrtpPolicy.NULL_AUTHENTICATION) { int tagLength = policy.AuthTagLength; // get original authentication and store in tempStore pkt.ReadRegionToBuff(pkt.GetLength() - tagLength, tagLength, tempStore); pkt.shrink(tagLength); // save computed authentication in tagStore AuthenticatePacketHMCSHA1(pkt, guessedROC); for (int i = 0; i < tagLength; i++) { if ((tempStore[i] & 0xff) != (tagStore[i] & 0xff)) { return(false); } } } // Decrypt packet switch (policy.EncType) { case SrtpPolicy.AESCM_ENCRYPTION: case SrtpPolicy.TWOFISH_ENCRYPTION: // using Counter Mode encryption ProcessPacketAESCM(pkt); break; case SrtpPolicy.AESF8_ENCRYPTION: case SrtpPolicy.TWOFISHF8_ENCRYPTION: // using F8 Mode encryption ProcessPacketAESF8(pkt); break; default: return(false); } Update(seqNo, guessedIndex); return(true); }