| /********** |
| This library is free software; you can redistribute it and/or modify it under |
| the terms of the GNU Lesser General Public License as published by the |
| Free Software Foundation; either version 3 of the License, or (at your |
| option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
| |
| This library is distributed in the hope that it will be useful, but WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| more details. |
| |
| You should have received a copy of the GNU Lesser General Public License |
| along with this library; if not, write to the Free Software Foundation, Inc., |
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| **********/ |
| // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
| // The SRTP 'Cryptographic Context', used in all of our uses of SRTP. |
| // Definition |
| |
| #ifndef _SRTP_CRYPTOGRAPHIC_CONTEXT_HH |
| #define _SRTP_CRYPTOGRAPHIC_CONTEXT_HH |
| |
| #ifndef _MIKEY_HH |
| #include "MIKEY.hh" |
| #endif |
| |
| class SRTPCryptographicContext { |
| public: |
| SRTPCryptographicContext(MIKEYState const& mikeyState); |
| virtual ~SRTPCryptographicContext(); |
| |
| // Authenticate (if necessary) and decrypt (if necessary) incoming SRTP and SRTCP packets. |
| // Returns True iff the packet is well-formed and authenticates OK. |
| // ("outPacketSize" will be <= "inPacketSize".) |
| Boolean processIncomingSRTPPacket(u_int8_t* buffer, unsigned inPacketSize, |
| unsigned& outPacketSize); |
| Boolean processIncomingSRTCPPacket(u_int8_t* buffer, unsigned inPacketSize, |
| unsigned& outPacketSize); |
| |
| // Encrypt (if necessary) and add an authentication tag (if necessary) to an outgoing |
| // RTCP packet. |
| // Returns True iff the packet is well-formed. |
| // ("outPacketSize" will be >= "inPacketSize"; there must be enough space at the end of |
| // "buffer" for the extra SRTCP tags (4+4+10 bytes).) |
| Boolean processOutgoingSRTCPPacket(u_int8_t* buffer, unsigned inPacketSize, |
| unsigned& outPacketSize); |
| |
| #ifndef NO_OPENSSL |
| private: |
| // Definitions specific to the "SRTP_AES128_CM_HMAC_SHA1_80" ciphersuite. |
| // Later generalize to support more SRTP ciphersuites ##### |
| #define SRTP_CIPHER_KEY_LENGTH (128/8) // in bytes |
| #define SRTP_CIPHER_SALT_LENGTH (112/8) // in bytes |
| #define SRTP_MKI_LENGTH 4 // in bytes |
| #define SRTP_AUTH_KEY_LENGTH (160/8) // in bytes |
| #define SRTP_AUTH_TAG_LENGTH (80/8) // in bytes |
| |
| struct derivedKeys { |
| u_int8_t cipherKey[SRTP_CIPHER_KEY_LENGTH]; |
| u_int8_t salt[SRTP_CIPHER_SALT_LENGTH]; |
| u_int8_t authKey[SRTP_AUTH_KEY_LENGTH]; |
| }; |
| |
| struct allDerivedKeys { |
| derivedKeys srtp; |
| derivedKeys srtcp; |
| }; |
| |
| typedef enum { |
| label_srtp_encryption = 0x00, |
| label_srtp_msg_auth = 0x01, |
| label_srtp_salt = 0x02, |
| label_srtcp_encryption = 0x03, |
| label_srtcp_msg_auth = 0x04, |
| label_srtcp_salt = 0x05 |
| } SRTPKeyDerivationLabel; |
| |
| unsigned generateSRTCPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, |
| u_int8_t* resultAuthenticationTag); |
| // returns the size of the resulting authentication tag |
| |
| Boolean verifySRTPAuthenticationTag(u_int8_t* dataToAuthenticate, unsigned numBytesToAuthenticate, |
| u_int32_t roc, u_int8_t const* authenticationTag); |
| Boolean verifySRTCPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, |
| u_int8_t const* authenticationTag); |
| |
| void decryptSRTPPacket(u_int64_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); |
| void decryptSRTCPPacket(u_int32_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); |
| |
| void encryptSRTCPPacket(u_int32_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); |
| |
| unsigned generateAuthenticationTag(derivedKeys& keysToUse, |
| u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, |
| u_int8_t* resultAuthenticationTag); |
| // returns the size of the resulting authentication tag |
| // "resultAuthenticationTag" must point to an array of at least SRTP_AUTH_TAG_LENGTH |
| Boolean verifyAuthenticationTag(derivedKeys& keysToUse, |
| u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, |
| u_int8_t const* authenticationTag); |
| |
| void cryptData(derivedKeys& keys, u_int64_t index, u_int32_t ssrc, |
| u_int8_t* data, unsigned numDataBytes); |
| |
| void performKeyDerivation(); |
| |
| void deriveKeysFromMaster(u_int8_t const* masterKey, u_int8_t const* salt, |
| allDerivedKeys& allKeysResult); |
| // used to implement "performKeyDerivation()" |
| void deriveSingleKey(u_int8_t const* masterKey, u_int8_t const* salt, |
| SRTPKeyDerivationLabel label, |
| unsigned resultKeyLength, u_int8_t* resultKey); |
| // used to implement "deriveKeysFromMaster()". |
| // ("resultKey" must be an existing buffer, of size >= "resultKeyLength") |
| |
| private: |
| MIKEYState const& fMIKEYState; |
| |
| // Master key + salt: |
| u_int8_t const* masterKeyPlusSalt() const { return fMIKEYState.keyData(); } |
| |
| u_int8_t const* masterKey() const { return &masterKeyPlusSalt()[0]; } |
| u_int8_t const* masterSalt() const { return &masterKeyPlusSalt()[SRTP_CIPHER_KEY_LENGTH]; } |
| |
| Boolean weEncryptSRTP() const { return fMIKEYState.encryptSRTP(); } |
| Boolean weEncryptSRTCP() const { return fMIKEYState.encryptSRTCP(); } |
| Boolean weAuthenticate() const { return fMIKEYState.useAuthentication(); } |
| u_int32_t MKI() const { return fMIKEYState.MKI(); } |
| |
| // Derived (i.e., session) keys: |
| allDerivedKeys fDerivedKeys; |
| |
| // State used for handling the reception of SRTP packets: |
| Boolean fHaveReceivedSRTPPackets; |
| u_int16_t fPreviousHighRTPSeqNum; |
| u_int32_t fROC; // rollover counter |
| |
| // State used for handling the sending of SRTCP packets: |
| u_int32_t fSRTCPIndex; |
| #endif |
| }; |
| |
| #endif |