Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F7159436
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
58 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.cpp b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.cpp
index 866cb4b9..8a77afe1 100644
--- a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.cpp
+++ b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.cpp
@@ -1,481 +1,497 @@
/*
Copyright (C) 2006 - 2012 Werner Dittmann
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 2.1 of the License, or (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*/
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <common/osSpecifics.h>
#include <CryptoContext.h>
#include <crypto/SrtpSymCrypto.h>
CryptoContext::CryptoContext( uint32_t ssrc,
int32_t roc,
int64_t key_deriv_rate,
const int32_t ealg,
const int32_t aalg,
uint8_t* master_key,
int32_t master_key_length,
uint8_t* master_salt,
int32_t master_salt_length,
int32_t ekeyl,
int32_t akeyl,
int32_t skeyl,
int32_t tagLength):
ssrcCtx(ssrc), mkiLength(0),mki(NULL), roc(roc),guessed_roc(0),
s_l(0),key_deriv_rate(key_deriv_rate), labelBase(0), seqNumSet(false),
macCtx(NULL), cipher(NULL), f8Cipher(NULL)
{
replay_window[0] = replay_window[1] = 0;
this->ealg = ealg;
this->aalg = aalg;
this->ekeyl = ekeyl;
this->akeyl = akeyl;
this->skeyl = skeyl;
this->master_key_length = master_key_length;
this->master_key = new uint8_t[master_key_length];
memcpy(this->master_key, master_key, master_key_length);
this->master_salt_length = master_salt_length;
this->master_salt = new uint8_t[master_salt_length];
memcpy(this->master_salt, master_salt, master_salt_length);
switch (ealg) {
case SrtpEncryptionNull:
n_e = 0;
k_e = NULL;
n_s = 0;
k_s = NULL;
break;
case SrtpEncryptionTWOF8:
f8Cipher = new SrtpSymCrypto(SrtpEncryptionTWOF8);
case SrtpEncryptionTWOCM:
n_e = ekeyl;
k_e = new uint8_t[n_e];
n_s = skeyl;
k_s = new uint8_t[n_s];
cipher = new SrtpSymCrypto(SrtpEncryptionTWOCM);
break;
case SrtpEncryptionAESF8:
f8Cipher = new SrtpSymCrypto(SrtpEncryptionAESF8);
case SrtpEncryptionAESCM:
n_e = ekeyl;
k_e = new uint8_t[n_e];
n_s = skeyl;
k_s = new uint8_t[n_s];
cipher = new SrtpSymCrypto(SrtpEncryptionAESCM);
break;
}
switch (aalg) {
case SrtpAuthenticationNull:
n_a = 0;
k_a = NULL;
this->tagLength = 0;
break;
case SrtpAuthenticationSha1Hmac:
+ n_a = akeyl;
+ k_a = new uint8_t[n_a];
+ this->tagLength = tagLength;
+ this->macCtx = createSha1HmacContext(k_a, n_a);
+ break;
+
case SrtpAuthenticationSkeinHmac:
n_a = akeyl;
k_a = new uint8_t[n_a];
this->tagLength = tagLength;
+ this->macCtx = createSkeinMacContext(k_a, n_a, tagLength*8, Skein512); // Skein MAC uses number of bits as MAC size, not just bytes
break;
}
}
/*
* memset_volatile is a volatile pointer to the memset function.
* You can call (*memset_volatile)(buf, val, len) or even
* memset_volatile(buf, val, len) just as you would call
* memset(buf, val, len), but the use of a volatile pointer
* guarantees that the compiler will not optimise the call away.
*/
static void * (*volatile memset_volatile)(void *, int, size_t) = memset;
-CryptoContext::~CryptoContext() {
+CryptoContext::~CryptoContext()
+{
+ if (macCtx) {
+ switch (aalg) {
+ case SrtpAuthenticationSha1Hmac:
+ freeSha1HmacContext(macCtx);
+ break;
+
+ case SrtpAuthenticationSkeinHmac:
+ freeSkeinMacContext(macCtx);
+ break;
+ }
+ macCtx = NULL;
+ }
if (mki)
delete [] mki;
if (master_key_length > 0) {
memset_volatile(master_key, 0, master_key_length);
master_key_length = 0;
delete [] master_key;
}
if (master_salt_length > 0) {
memset_volatile(master_salt, 0, master_salt_length);
master_salt_length = 0;
delete [] master_salt;
}
if (n_e > 0) {
memset_volatile(k_e, 0, n_e);
n_e = 0;
delete [] k_e;
}
if (n_s > 0) {
memset_volatile(k_s, 0, n_s);
n_s = 0;
delete [] k_s;
}
if (n_a > 0) {
memset_volatile(k_a, 0, n_a);
n_a = 0;
delete [] k_a;
}
if (cipher != NULL) {
delete cipher;
cipher = NULL;
}
if (f8Cipher != NULL) {
delete f8Cipher;
f8Cipher = NULL;
}
}
void CryptoContext::srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, uint64_t index, uint32_t ssrc ) {
if (ealg == SrtpEncryptionNull) {
return;
}
if (ealg == SrtpEncryptionAESCM || ealg == SrtpEncryptionTWOCM) {
/* Compute the CM IV (refer to chapter 4.1.1 in RFC 3711):
*
* k_s XX XX XX XX XX XX XX XX XX XX XX XX XX XX
* SSRC XX XX XX XX
* index XX XX XX XX XX XX
* ------------------------------------------------------XOR
* IV XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
*/
unsigned char iv[16];
memcpy(iv, k_s, 4);
int i;
for (i = 4; i < 8; i++ ) {
iv[i] = (0xFF & (ssrc >> ((7-i)*8))) ^ k_s[i];
}
for (i = 8; i < 14; i++ ) {
iv[i] = (0xFF & (unsigned char)(index >> ((13-i)*8) ) ) ^ k_s[i];
}
iv[14] = iv[15] = 0;
cipher->ctr_encrypt(payload, paylen, iv);
}
if (ealg == SrtpEncryptionAESF8 || ealg == SrtpEncryptionTWOF8) {
/* Create the F8 IV (refer to chapter 4.1.2.2 in RFC 3711):
*
* IV = 0x00 || M || PT || SEQ || TS || SSRC || ROC
* 8Bit 1bit 7bit 16bit 32bit 32bit 32bit
* ------------\ /--------------------------------------------------
* XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
*/
unsigned char iv[16];
uint32_t *ui32p = (uint32_t *)iv;
memcpy(iv, pkt, 12);
iv[0] = 0;
// set ROC in network order into IV
ui32p[3] = zrtpHtonl(roc);
cipher->f8_encrypt(payload, paylen, iv, f8Cipher);
}
}
/* Warning: tag must have been initialized */
void CryptoContext::srtpAuthenticate(uint8_t* pkt, uint32_t pktlen, uint32_t roc, uint8_t* tag )
{
if (aalg == SrtpAuthenticationNull) {
return;
}
int32_t macL;
unsigned char temp[20];
const unsigned char* chunks[3];
unsigned int chunkLength[3];
uint32_t beRoc = zrtpHtonl(roc);
chunks[0] = pkt;
chunkLength[0] = pktlen;
chunks[1] = (unsigned char *)&beRoc;
chunkLength[1] = 4;
chunks[2] = NULL;
switch (aalg) {
case SrtpAuthenticationSha1Hmac:
hmacSha1Ctx(macCtx,
chunks, // data chunks to hash
chunkLength, // length of the data to hash
temp, &macL);
/* truncate the result */
memcpy(tag, temp, getTagLength());
break;
case SrtpAuthenticationSkeinHmac:
macSkeinCtx(macCtx,
chunks, // data chunks to hash
chunkLength, // length of the data to hash
temp);
/* truncate the result */
memcpy(tag, temp, getTagLength());
break;
}
}
/* used by the key derivation method */
static void computeIv(unsigned char* iv, uint64_t label, uint64_t index,
int64_t kdv, unsigned char* master_salt)
{
uint64_t key_id;
if (kdv == 0) {
key_id = label << 48;
}
else {
key_id = ((label << 48) | (index / kdv));
}
//printf( "Key_ID: %llx\n", key_id );
/* compute the IV
key_id: XX XX XX XX XX XX XX
master_salt: XX XX XX XX XX XX XX XX XX XX XX XX XX XX
------------------------------------------------------------ XOR
IV: XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
*/
int i;
for (i = 0; i < 7 ; i++ ) {
iv[i] = master_salt[i];
}
for (i = 7; i < 14 ; i++ ) {
iv[i] = (unsigned char)(0xFF & (key_id >> (8*(13-i)))) ^ master_salt[i];
}
iv[14] = iv[15] = 0;
}
/* Derive the srtp session keys from the master key */
void CryptoContext::deriveSrtpKeys(uint64_t index)
{
uint8_t iv[16];
// prepare cipher to compute derived keys.
cipher->setNewKey(master_key, master_key_length);
memset(master_key, 0, master_key_length);
// compute the session encryption key
uint64_t label = labelBase + 0;
computeIv(iv, label, index, key_deriv_rate, master_salt);
cipher->get_ctr_cipher_stream(k_e, n_e, iv);
// compute the session authentication key
label = labelBase + 0x01;
computeIv(iv, label, index, key_deriv_rate, master_salt);
cipher->get_ctr_cipher_stream(k_a, n_a, iv);
// Initialize MAC context with the derived key
switch (aalg) {
case SrtpAuthenticationSha1Hmac:
- macCtx = &hmacCtx.hmacSha1Ctx;
- macCtx = initializeSha1HmacContext(macCtx, k_a, n_a);
+ initializeSha1HmacContext(macCtx, k_a, n_a);
break;
case SrtpAuthenticationSkeinHmac:
- macCtx = &hmacCtx.hmacSkeinCtx;
-
- // Skein MAC uses number of bits as MAC size, not just bytes
- macCtx = initializeSkeinMacContext(macCtx, k_a, n_a, tagLength*8, Skein512);
+ initializeSkeinMacContext(macCtx, k_a, n_a, tagLength*8, Skein512); // Skein MAC uses number of bits as MAC size, not just bytes
break;
}
memset(k_a, 0, n_a);
// compute the session salt
label = labelBase + 0x02;
computeIv(iv, label, index, key_deriv_rate, master_salt);
cipher->get_ctr_cipher_stream(k_s, n_s, iv);
memset(master_salt, 0, master_salt_length);
// as last step prepare cipher with derived key.
cipher->setNewKey(k_e, n_e);
if (f8Cipher != NULL)
cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s);
memset(k_e, 0, n_e);
}
/* Based on the algorithm provided in Appendix A - draft-ietf-srtp-05.txt */
uint64_t CryptoContext::guessIndex(uint16_t new_seq_nb )
{
/*
* Initialize the sequences number on first call that uses the
* sequence number. Either GuessIndex() or checkReplay().
*/
if (!seqNumSet) {
seqNumSet = true;
s_l = new_seq_nb;
}
if (s_l < 32768) {
if (new_seq_nb - s_l > 32768) {
guessed_roc = roc - 1;
}
else {
guessed_roc = roc;
}
}
else {
if (s_l - 32768 > new_seq_nb) {
guessed_roc = roc + 1;
}
else {
guessed_roc = roc;
}
}
return ((uint64_t)guessed_roc) << 16 | new_seq_nb;
}
bool CryptoContext::checkReplay(uint16_t newSeq)
{
if ( aalg == SrtpAuthenticationNull && ealg == SrtpEncryptionNull ) {
/* No security policy, don't use the replay protection */
return true;
}
/*
* Initialize the sequences number on first call that uses the
* sequence number. Either guessIndex() or checkReplay().
*/
if (!seqNumSet) {
seqNumSet = true;
s_l = newSeq;
}
uint64_t guessed_index = guessIndex(newSeq);
uint64_t local_index = (((uint64_t)roc) << 16) | s_l;
int64_t delta = guessed_index - local_index;
if (delta > 0) {
return true; /* Packet not yet received*/
}
else {
if (-delta >= REPLAY_WINDOW_SIZE) {
return false; /* Packet too old */
}
delta = -delta;
int idx = delta / 64;
uint64_t bit = 1UL << (delta % 64);
if ((replay_window[idx] & bit) == bit) {
return false; /* Packet already received ! */
}
else {
return true; /* Packet not yet received */
}
}
}
// This function assumes that it never gets a sequence number that is out of order
// greater or equal than REPLAY_WINDOW_SIZE. Thus an application MUST perform a
// replay check first and discard any packet which fails this check. This restriction
// applies to older packets only, a new (not seen) packet's sequence number can jump
// ahead by more than REPLAY_WINDOW_SIZE.
void CryptoContext::update(uint16_t newSeq)
{
// Get the index of the new sequence number and compute the delta to the
// index of the highest sequence number we received so far. If the delta
// is negative then we received an older packet, thus we will not
// update the locally stored remote sequence number (s_l) below.
int64_t delta = guessIndex(newSeq) - (((uint64_t)roc) << 16 | s_l );
int64_t rocDelta = delta;
uint64_t carry = 0;
// update the replay shift register
// The shift register array stores bits of newer packets (higher sequence numbers) at
// index 0 and shifts older packets (lower sequence numbers) left to index one
if (delta > 0) { // We got a new packet, no yet seen
if (delta >= REPLAY_WINDOW_SIZE) {
replay_window[0] = 1;
replay_window[1] = 0;
}
else {
if (delta < REPLAY_WINDOW_SIZE/2) {
carry = replay_window[0] >> ((REPLAY_WINDOW_SIZE/2) - delta);
replay_window[0] = (replay_window[0] << delta) | 1;
replay_window[1] = (replay_window[1] << delta) | carry;
}
else {
replay_window[1] = replay_window[0] << (delta - REPLAY_WINDOW_SIZE/2);
replay_window[0] = 1;
}
}
}
else {
delta = -delta;
int idx = delta / 64;
uint64_t bit = 1UL << (delta % 64);
replay_window[idx] |= bit;
}
// update the locally stored ROC and highest sequence number if we received a not
// yet received packet, i.e. the delta is > 0
if (rocDelta > 0 && newSeq > s_l) {
s_l = newSeq;
}
// Reset local stored sequence number (low 16 bits) also if ROC increases
// The guessed_roc is bigger than roc only if we received a not yet seen packet.
if (guessed_roc > roc) {
roc = guessed_roc;
s_l = newSeq;
}
}
CryptoContext* CryptoContext::newCryptoContextForSSRC(uint32_t ssrc, int roc, int64_t keyDerivRate)
{
CryptoContext* pcc = new CryptoContext(
ssrc,
roc, // Roll over Counter,
keyDerivRate, // keyderivation << 48,
this->ealg, // encryption algo
this->aalg, // authentication algo
this->master_key, // Master Key
this->master_key_length, // Master Key length
this->master_salt, // Master Salt
this->master_salt_length, // Master Salt length
this->ekeyl, // encryption keyl
this->akeyl, // authentication key len
this->skeyl, // session salt len
this->tagLength); // authentication tag len
return pcc;
}
diff --git a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.h b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.h
index daf0c607..5e47e3ed 100644
--- a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.h
+++ b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContext.h
@@ -1,479 +1,468 @@
/*
Copyright (C) 2006 - 2012 Werner Dittmann
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 2.1 of the License, or (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CRYPTOCONTEXT_H
#define CRYPTOCONTEXT_H
/**
* @file CryptoContext.h
* @brief The C++ SRTP implementation
* @ingroup Z_SRTP
* @{
*/
#define REPLAY_WINDOW_SIZE 128
const int SrtpAuthenticationNull = 0;
const int SrtpAuthenticationSha1Hmac = 1;
const int SrtpAuthenticationSkeinHmac = 2;
const int SrtpEncryptionNull = 0;
const int SrtpEncryptionAESCM = 1;
const int SrtpEncryptionAESF8 = 2;
const int SrtpEncryptionTWOCM = 3;
const int SrtpEncryptionTWOF8 = 4;
// Check if included via CryptoContextCtrl.cpp - avoid double definitions
#ifndef CRYPTOCONTEXTCTRL_H
#include <stdint.h>
#ifdef ZRTP_OPENSSL
#include <openssl/hmac.h>
#else
#include <crypto/hmac.h>
#endif
#include <cryptcommon/macSkein.h>
class SrtpSymCrypto;
/**
* @brief Implementation for a SRTP cryptographic context.
*
* This class holds data and provides functions that implement a
* cryptographic context for SRTP. Refer to RFC 3711, chapter 3.2 for some
* more detailed information about the SRTP cryptographic context.
*
* Each SRTP cryptographic context uses a RTP source identified by
* its SSRC. Thus you can independently protect each source inside a RTP
* session.
*
* Key management mechanisms negotiate the parameters for the SRTP
* cryptographic context, such as master key, key length, authentication
* length and so on. The key management mechanisms are not part of
* SRTP. Refer to MIKEY (RFC 3880) or to Phil Zimmermann's ZRTP protocol
* (RFC6189). After key management negotiated the data the application can
* setup the SRTP cryptographic context and enable SRTP processing.
*
* This SRTP context implementation supports RTP only.
*
* A short eample how to setup a SRTP CryptoContext:
@verbatim
// First some key and salt data - this data is just for demo purposes
uint8 masterKey[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
uint8 masterSalt[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d };
...
CryptoContext* cryptoCtxSend =
new CryptoContext(0xfeedbacc,
0, // roc,
0L, // keyderivation rate << 48,
SrtpEncryptionAESCM, // encryption algo
SrtpAuthenticationSha1Hmac, // authtication algo
masterKey, // Master Key data
128 / 8, // Master Key length in bytes
masterSalt, // Master Salt data
112 / 8, // Master Salt length in bytes
128 / 8, // encryption keylength in bytes
160 / 8, // authentication key length in bytes (SHA1)
112 / 8, // session salt length in bytes
80 / 8); // authentication tag length in bytes
cryptoCtxSend->deriveSrtpKeys(0);
....
// To protect a RTP packet
// buffer: pointer to the RTP packet, length of the RTP data, newLength is a
// pointer to a size_t that gets the updated length.
bool rc = SrtpHandler::protect(cryptoCtxSend, buffer, length, newLength);
// To unprotect a SRTP packet:
// buffer: pointer to the RTP packet, length of the SRTP data, newLength is a
// pointer to a size_t that gets the updated length.
int32_t rc = SrtpHandler::unprotect(cryptoCtxRecv, buffer, length, newLength);
@endverbatim
*
* @note You need two CryptoContext instances - one for the sending channel the
* other one for the receiving channel.
*
* Before an appliction can use a CryptoContext it must call the key derivation
* function deriveSrtpKeys() first. Only then this SRTP cryptographic context is ready
* to protect or unprotect a RTP SSRC stream.
*
* Together with the newCryptoContextForSSRC() function an application can prepare a
* CryptoContext and save it as template. Once it needs a new CryptoContext, say
* for a new SSRC, it calls newCryptoContextForSSRC() on the saved context to get an
* initialized copy and then call deriveSrtpKeys() to compute and process the keys.
*
* @note A saved, pre-initialized template contains the non-processed keys. Only
* the method deriveSrtpKeys() processes the keys and cleares them. Thus don't store
* CryptoContext templates if the application cannot protect the templates against
* reading from other possibly rogue applications.
*
* @sa SrtpHandler
*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*/
class CryptoContext {
public:
/**
* @brief Constructor for an active SRTP cryptographic context.
*
* This constructor creates an pre-initialized SRTP cryptographic context were
* algorithms are allocated, keys are stored and so on. An application can
* call newCryptoContextForSSRC() to get a full copy of this pre-initialized
* CryptoContext.
*
*
* @param ssrc
* The RTP SSRC that this SRTP cryptographic context belongs to.
*
* @param roc
* The initial Roll-Over-Counter according to RFC 3711. These are the
* upper 32 bit of the overall 48 bit SRTP packet index. Usually set to zero.
* Refer to chapter 3.2.1 of the RFC.
*
* @param keyDerivRate
* The key derivation rate defines when to recompute the SRTP session
* keys. Refer to chapter 4.3.1 in the RFC.
*
* @param ealg
* The encryption algorithm to use. Possible values are <code>
* SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8,
* SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1
* for AESCM (Counter mode) and 4.1.2 for AES F8 mode.
*
* @param aalg
* The authentication algorithm to use. Possible values are <code>
* SrtpEncryptionNull, SrtpAuthenticationSha1Hmac, SrtpAuthenticationSkeinHmac
* </code>.
*
* @param masterKey
* Pointer to the master key for this SRTP cryptographic context.
* Must point to <code>masterKeyLength</code> bytes. Refer to chapter
* 3.2.1 of the RFC about the role of the master key.
*
* @param masterKeyLength
* The length in bytes of the master key in bytes. The length must
* match the selected encryption algorithm. Because SRTP uses AES
* based encryption only, then master key length may be 16 or 32
* bytes (128 or 256 bit master key)
*
* @param masterSalt
* SRTP uses the master salt to generate the initialization vector
* that in turn is input to compute the session key, session
* authentication key and the session salt.
*
* @param masterSaltLength
* The length in bytes of the master salt data in bytes. According to
* RFC3711 the standard value for the master salt length should
* be 14 bytes (112 bit).
*
* @param ekeyl
* The length in bytes of the session encryption key that SRTP shall
* generate and use. Usually the same length as for the master key
* length, however you may use a different length as well.
*
* @param akeyl
* The length in bytes of the session authentication key. SRTP
* computes this key and uses it as input to the authentication
* algorithm.
* This is usually 160 bits (20 bytes) for @c SrtpAuthenticationSha1Hmac
* and 256 bits (32 bytes) for @c SrtpAuthenticationSkeinHmac.
*
* @param skeyl
* The length in bytes of the session salt. SRTP computes this salt
* key and uses it as input during encryption. The length usually
* is the same as the master salt length.
*
* @param tagLength
* The length is bytes of the authentication tag that SRTP appends
* to the RTP packet. The @c CryptoContext supports @c SrtpAuthenticationSha1Hmac
* with 4 and 10 byte (32 and 80 bits) and @c SrtpAuthenticationSkeinHmac
* with 4 and 8 bytes (32 and 64 bits) tag length. Refer to chapter 4.2. in RFC 3711.
*/
CryptoContext(uint32_t ssrc, int32_t roc,
int64_t keyDerivRate,
const int32_t ealg,
const int32_t aalg,
uint8_t* masterKey,
int32_t masterKeyLength,
uint8_t* masterSalt,
int32_t masterSaltLength,
int32_t ekeyl,
int32_t akeyl,
int32_t skeyl,
int32_t tagLength);
/**
* @brief Destructor.
*
* Cleans the SRTP cryptographic context.
*/
~CryptoContext();
/**
* @brief Set the Roll-Over-Counter.
*
* Ths method sets the upper 32 bit of the 48 bit SRTP packet index
* (the roll-over-part)
*
* @param r
* The roll-over-counter
*/
inline void setRoc(uint32_t r) { roc = r; }
/**
* @brief Get the Roll-Over-Counter.
*
* Ths method get the upper 32 bit of the 48 bit SRTP packet index
* (the roll-over-part)
*
* @return The roll-over-counter
*/
inline uint32_t getRoc() const { return roc; }
/**
* @brief Perform SRTP encryption.
*
* This method encrypts <em>and</em> decrypts SRTP payload data. Plain
* data gets encrypted, encrypted data get decrypted.
*
* @param pkt
* Pointer to RTP packet buffer, used for F8.
*
* @param payload
* The data to encrypt.
*
* @param paylen
* Length of payload.
*
* @param index
* The 48 bit SRTP packet index. See the <code>guessIndex</code>
* method.
*
* @param ssrc
* The RTP SSRC data in <em>host</em> order.
*/
void srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, uint64_t index, uint32_t ssrc);
/**
* @brief Compute the authentication tag.
*
* Compute the authentication tag according the the paramters in the
* SRTP Cryptograhic context.
*
* @param pkt
* Pointer to RTP packet buffer that contains the data to authenticate.
*
* @param pktlen
* Length of the RTP packet buffer
*
* @param roc
* The 32 bit SRTP roll-over-counter.
*
* @param tag
* Points to a buffer that hold the computed tag. This buffer must
* be able to hold <code>tagLength</code> bytes.
*/
void srtpAuthenticate(uint8_t* pkt, uint32_t pktlen, uint32_t roc, uint8_t* tag);
/**
* @brief Perform key derivation according to SRTP specification
*
* This method computes the session key, session authentication key and the
* session salt key. This method must be called at least once after the
* SRTP Cryptograhic context was set up.
*
* This method clears the key data once it was processed by the encryptions'
* set key functions.
*
* @param index
* The 48 bit SRTP packet index. See the <code>guessIndex</code>
* method. Usually 0.
*/
void deriveSrtpKeys(uint64_t index);
/**
* @brief Compute (guess) the new SRTP index based on the sequence number of
* a received RTP packet.
*
* The method uses the algorithm show in RFC3711, Appendix A, to compute
* the new index.
*
* @param newSeqNumber
* The sequence number of the received RTP packet in host order.
*
* @return The new SRTP packet index
*/
uint64_t guessIndex(uint16_t newSeqNumber);
/**
* @brief Check for packet replay.
*
* The method check if a received packet is either to old or was already
* received.
*
* The method supports a 64 packet history relative the the given
* sequence number.
*
* @param newSeqNumber
* The sequence number of the received RTP packet in host order.
*
* @return <code>true</code> if no replay, <code>false</code> if packet
* is too old ar was already received.
*/
bool checkReplay(uint16_t newSeqNumber);
/**
* @brief Update the SRTP packet index.
*
* Call this method after all checks were successful. See chapter
* 3.3.1 in the RFC when to update the ROC and ROC processing.
*
* @param newSeqNumber
* The sequence number of the received RTP packet in host order.
*/
void update(uint16_t newSeqNumber);
/**
* @brief Get the length of the SRTP authentication tag in bytes.
*
* @return the length of the authentication tag.
*/
int32_t getTagLength() const { return tagLength; }
/**
* @brief Get the length of the MKI in bytes.
*
* @return the length of the MKI.
*/
int32_t getMkiLength() const { return mkiLength; }
/**
* @brief Get the SSRC of this SRTP Cryptograhic context.
*
* @return the SSRC.
*/
uint32_t getSsrc() const { return ssrcCtx; }
/**
* @brief Set the start (base) number to compute the PRF labels.
*
* Refer to RFC3711, chapters 4.3.1 and 4.3.2 about values for labels.
* CryptoContext computes the labes as follows:
*
* - labelBase + 0 -> encryption label
* - labelBase + 1 -> authentication label
* - labelBase + 2 -> salting key label
*
* The CryptoContext constructor initializes CryptoContext::labelBase
* with 0 to comply with RFC 3711 label values.
*
* Applications may set the #labelBase to other values to use the CryptoContext
* for other purposes.
*/
void setLabelbase(uint8_t base) { labelBase = base; }
/**
* @brief Derive a new Crypto Context for use with a new SSRC
*
* This method returns a new Crypto Context initialized with the data
* of this crypto context. Replacing the SSRC, Roll-over-Counter, and
* the key derivation rate the application can use this Crypto Context
* to encrypt / decrypt a new stream (Synchronization source) inside
* one RTP session.
*
* Before the application can use this crypto context it must call deriveSrtpKeys().
*
* @param ssrc
* The SSRC for this context
* @param roc
* The Roll-Over-Counter for this context, usually 0
* @param keyDerivRate
* The key derivation rate for this context, usally 0
* @return
* a new CryptoContext with all relevant data set.
*/
CryptoContext* newCryptoContextForSSRC(uint32_t ssrc, int roc, int64_t keyDerivRate);
private:
- typedef union _hmacCtx {
- SkeinCtx_t hmacSkeinCtx;
-#ifdef ZRTP_OPENSSL
- HMAC_CTX hmacSha1Ctx;
-#else
- hmacSha1Context hmacSha1Ctx;
-#endif
- } HmacCtx;
-
-
uint32_t ssrcCtx;
uint32_t mkiLength;
uint8_t* mki;
uint32_t roc;
uint32_t guessed_roc;
uint16_t s_l;
int64_t key_deriv_rate;
/* bitmask for replay check */
uint64_t replay_window[2];
uint8_t* master_key;
uint32_t master_key_length;
uint8_t* master_salt;
uint32_t master_salt_length;
/* Session Encryption, Authentication keys, Salt */
int32_t n_e;
uint8_t* k_e;
int32_t n_a;
uint8_t* k_a;
int32_t n_s;
uint8_t* k_s;
int32_t ealg;
int32_t aalg;
int32_t ekeyl;
int32_t akeyl;
int32_t skeyl;
int32_t tagLength;
uint8_t labelBase;
bool seqNumSet;
- void* macCtx;
- HmacCtx hmacCtx;
+ void* macCtx;
SrtpSymCrypto* cipher;
SrtpSymCrypto* f8Cipher;
};
#endif
/**
* @}
*/
#endif
diff --git a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.cpp b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.cpp
index ab2d0607..ea1531b5 100644
--- a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.cpp
+++ b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.cpp
@@ -1,393 +1,409 @@
/*
Copyright (C) 2011 - 2012 Werner Dittmann
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 2.1 of the License, or (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*/
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <common/osSpecifics.h>
#include <CryptoContextCtrl.h>
#include <CryptoContext.h>
#include <crypto/SrtpSymCrypto.h>
CryptoContextCtrl::CryptoContextCtrl(uint32_t ssrc,
const int32_t ealg,
const int32_t aalg,
uint8_t* master_key,
int32_t master_key_length,
uint8_t* master_salt,
int32_t master_salt_length,
int32_t ekeyl,
int32_t akeyl,
int32_t skeyl,
int32_t tagLength):
ssrcCtx(ssrc), mkiLength(0),mki(NULL), replay_window(0), srtcpIndex(0),
labelBase(3), macCtx(NULL), cipher(NULL), f8Cipher(NULL) // SRTCP labels start at 3
{
this->ealg = ealg;
this->aalg = aalg;
this->ekeyl = ekeyl;
this->akeyl = akeyl;
this->skeyl = skeyl;
this->master_key_length = master_key_length;
this->master_key = new uint8_t[master_key_length];
memcpy(this->master_key, master_key, master_key_length);
this->master_salt_length = master_salt_length;
this->master_salt = new uint8_t[master_salt_length];
memcpy(this->master_salt, master_salt, master_salt_length);
switch (ealg) {
case SrtpEncryptionNull:
n_e = 0;
k_e = NULL;
n_s = 0;
k_s = NULL;
break;
case SrtpEncryptionTWOF8:
f8Cipher = new SrtpSymCrypto(SrtpEncryptionTWOF8);
case SrtpEncryptionTWOCM:
n_e = ekeyl;
k_e = new uint8_t[n_e];
n_s = skeyl;
k_s = new uint8_t[n_s];
cipher = new SrtpSymCrypto(SrtpEncryptionTWOCM);
break;
case SrtpEncryptionAESF8:
f8Cipher = new SrtpSymCrypto(SrtpEncryptionAESF8);
case SrtpEncryptionAESCM:
n_e = ekeyl;
k_e = new uint8_t[n_e];
n_s = skeyl;
k_s = new uint8_t[n_s];
cipher = new SrtpSymCrypto(SrtpEncryptionAESCM);
break;
}
switch (aalg) {
case SrtpAuthenticationNull:
n_a = 0;
k_a = NULL;
this->tagLength = 0;
break;
case SrtpAuthenticationSha1Hmac:
+ n_a = akeyl;
+ k_a = new uint8_t[n_a];
+ this->tagLength = tagLength;
+ this->macCtx = createSha1HmacContext(k_a, n_a);
+ break;
+
case SrtpAuthenticationSkeinHmac:
n_a = akeyl;
k_a = new uint8_t[n_a];
this->tagLength = tagLength;
+ this->macCtx = createSkeinMacContext(k_a, n_a, tagLength*8, Skein512); // Skein MAC uses number of bits as MAC size, not just bytes
break;
}
}
/*
* memset_volatile is a volatile pointer to the memset function.
* You can call (*memset_volatile)(buf, val, len) or even
* memset_volatile(buf, val, len) just as you would call
* memset(buf, val, len), but the use of a volatile pointer
* guarantees that the compiler will not optimise the call away.
*/
static void * (*volatile memset_volatile)(void *, int, size_t) = memset;
-CryptoContextCtrl::~CryptoContextCtrl(){
+CryptoContextCtrl::~CryptoContextCtrl()
+{
+ if (macCtx) {
+ switch (aalg) {
+ case SrtpAuthenticationSha1Hmac:
+ freeSha1HmacContext(macCtx);
+ break;
+
+ case SrtpAuthenticationSkeinHmac:
+ freeSkeinMacContext(macCtx);
+ break;
+ }
+ macCtx = NULL;
+ }
if (mki)
delete [] mki;
if (master_key_length > 0) {
memset_volatile(master_key, 0, master_key_length);
master_key_length = 0;
delete [] master_key;
}
if (master_salt_length > 0) {
memset_volatile(master_salt, 0, master_salt_length);
master_salt_length = 0;
delete [] master_salt;
}
if (n_e > 0) {
memset_volatile(k_e, 0, n_e);
n_e = 0;
delete [] k_e;
}
if (n_s > 0) {
memset_volatile(k_s, 0, n_s);
n_s = 0;
delete [] k_s;
}
if (n_a > 0) {
n_a = 0;
memset_volatile(k_a, 0, n_a);
delete [] k_a;
}
if (cipher != NULL) {
delete cipher;
cipher = NULL;
}
if (f8Cipher != NULL) {
delete f8Cipher;
f8Cipher = NULL;
}
}
void CryptoContextCtrl::srtcpEncrypt( uint8_t* rtp, int32_t len, uint32_t index, uint32_t ssrc )
{
if (ealg == SrtpEncryptionNull) {
return;
}
if (ealg == SrtpEncryptionAESCM || ealg == SrtpEncryptionTWOCM) {
/* Compute the CM IV (refer to chapter 4.1.1 in RFC 3711):
*
* k_s XX XX XX XX XX XX XX XX XX XX XX XX XX XX
* SSRC XX XX XX XX
* index XX XX XX XX
* ------------------------------------------------------XOR
* IV XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
*/
unsigned char iv[16];
iv[0] = k_s[0];
iv[1] = k_s[1];
iv[2] = k_s[2];
iv[3] = k_s[3];
// The shifts transform the ssrc and index into network order
iv[4] = ((ssrc >> 24) & 0xff) ^ k_s[4];
iv[5] = ((ssrc >> 16) & 0xff) ^ k_s[5];
iv[6] = ((ssrc >> 8) & 0xff) ^ k_s[6];
iv[7] = (ssrc & 0xff) ^ k_s[7];
iv[8] = k_s[8];
iv[9] = k_s[9];
iv[10] = ((index >> 24) & 0xff) ^ k_s[10];
iv[11] = ((index >> 16) & 0xff) ^ k_s[11];
iv[12] = ((index >> 8) & 0xff) ^ k_s[12];
iv[13] = (index & 0xff) ^ k_s[13];
iv[14] = iv[15] = 0;
cipher->ctr_encrypt(rtp, len, iv);
}
if (ealg == SrtpEncryptionAESF8 || ealg == SrtpEncryptionTWOF8) {
unsigned char iv[16];
// 4 bytes of the iv are zero
// the first byte of the RTP header is not used.
iv[0] = 0;
iv[1] = 0;
iv[2] = 0;
iv[3] = 0;
// Need the encryption flag
index = index | 0x80000000;
// set the index and the encrypt flag in network order into IV
iv[4] = index >> 24;
iv[5] = index >> 16;
iv[6] = index >> 8;
iv[7] = index;
// The fixed header follows and fills the rest of the IV
memcpy(iv+8, rtp, 8);
cipher->f8_encrypt(rtp, len, iv, f8Cipher);
}
}
/* Warning: tag must have been initialized */
void CryptoContextCtrl::srtcpAuthenticate(uint8_t* rtp, int32_t len, uint32_t index, uint8_t* tag )
{
if (aalg == SrtpAuthenticationNull) {
return;
}
int32_t macL;
unsigned char temp[20];
const unsigned char* chunks[3];
unsigned int chunkLength[3];
uint32_t beIndex = zrtpHtonl(index);
chunks[0] = rtp;
chunkLength[0] = len;
chunks[1] = (unsigned char *)&beIndex;
chunkLength[1] = 4;
chunks[2] = NULL;
switch (aalg) {
case SrtpAuthenticationSha1Hmac:
hmacSha1Ctx(macCtx,
chunks, // data chunks to hash
chunkLength, // length of the data to hash
temp, &macL);
/* truncate the result */
memcpy(tag, temp, getTagLength());
break;
case SrtpAuthenticationSkeinHmac:
macSkeinCtx(macCtx,
chunks, // data chunks to hash
chunkLength, // length of the data to hash
temp);
/* truncate the result */
memcpy(tag, temp, getTagLength());
break;
}
}
/* used by the key derivation method */
static void computeIv(unsigned char* iv, uint8_t label, uint8_t* master_salt)
{
//printf( "Key_ID: %llx\n", key_id );
/* compute the IV
key_id: XX XX XX XX XX XX XX
master_salt: XX XX XX XX XX XX XX XX XX XX XX XX XX XX
------------------------------------------------------------ XOR
IV: XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
*/
memcpy(iv, master_salt, 14);
iv[7] ^= label;
iv[14] = iv[15] = 0;
}
/* Derives the srtp session keys from the master key */
void CryptoContextCtrl::deriveSrtcpKeys()
{
uint8_t iv[16];
// prepare cipher to compute derived keys.
cipher->setNewKey(master_key, master_key_length);
memset(master_key, 0, master_key_length);
// compute the session encryption key
uint8_t label = labelBase;
computeIv(iv, label, master_salt);
cipher->get_ctr_cipher_stream(k_e, n_e, iv);
// compute the session authentication key
label = labelBase + 1;
computeIv(iv, label, master_salt);
cipher->get_ctr_cipher_stream(k_a, n_a, iv);
// Initialize MAC context with the derived key
switch (aalg) {
case SrtpAuthenticationSha1Hmac:
- macCtx = &hmacCtx.hmacSha1Ctx;
- macCtx = initializeSha1HmacContext(macCtx, k_a, n_a);
+ initializeSha1HmacContext(macCtx, k_a, n_a);
break;
case SrtpAuthenticationSkeinHmac:
- macCtx = &hmacCtx.hmacSkeinCtx;
-
- // Skein MAC uses number of bits as MAC size, not just bytes
- macCtx = initializeSkeinMacContext(macCtx, k_a, n_a, tagLength*8, Skein512);
+ initializeSkeinMacContext(macCtx, k_a, n_a, tagLength*8, Skein512); // Skein MAC uses number of bits as MAC size, not just bytes
break;
}
memset(k_a, 0, n_a);
// compute the session salt
label = labelBase + 2;
computeIv(iv, label, master_salt);
cipher->get_ctr_cipher_stream(k_s, n_s, iv);
memset(master_salt, 0, master_salt_length);
// as last step prepare cipher with derived key.
cipher->setNewKey(k_e, n_e);
if (f8Cipher != NULL)
cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s);
memset(k_e, 0, n_e);
}
bool CryptoContextCtrl::checkReplay( uint32_t index )
{
if ( aalg == SrtpAuthenticationNull && ealg == SrtpEncryptionNull ) {
/* No security policy, don't use the replay protection */
return true;
}
int64_t delta = index - s_l;
if (delta > 0) {
/* Packet not yet received*/
return true;
}
else {
if( -delta >= REPLAY_WINDOW_SIZE ) {
return false; /* Packet too old */
}
else {
if((replay_window >> (-delta)) & 0x1) {
return false; /* Packet already received ! */
}
else {
return true; /* Packet not yet received */
}
}
}
}
void CryptoContextCtrl::update(uint32_t index)
{
int64_t delta = index - s_l;
/* update the replay bitmask */
if( delta > 0 ){
replay_window = replay_window << delta;
replay_window |= 1;
}
else {
replay_window |= ( 1 << -delta );
}
if (index > s_l)
s_l = index;
}
CryptoContextCtrl* CryptoContextCtrl::newCryptoContextForSSRC(uint32_t ssrc)
{
CryptoContextCtrl* pcc = new CryptoContextCtrl(
ssrc,
this->ealg, // encryption algo
this->aalg, // authentication algo
this->master_key, // Master Key
this->master_key_length, // Master Key length
this->master_salt, // Master Salt
this->master_salt_length, // Master Salt length
this->ekeyl, // encryption keyl
this->akeyl, // authentication key len
this->skeyl, // session salt len
this->tagLength); // authentication tag len
return pcc;
}
diff --git a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.h b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.h
index 0b19b834..00b4fc61 100644
--- a/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.h
+++ b/deps/pjsip/third_party/zsrtp/zrtp/srtp/CryptoContextCtrl.h
@@ -1,348 +1,341 @@
/*
Copyright (C) 2011 - 2012 Werner Dittmann
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 2.1 of the License, or (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CRYPTOCONTEXTCTRL_H
#define CRYPTOCONTEXTCTRL_H
/**
* @file CryptoContextCtrl.h
* @brief The C++ SRTCP implementation
* @ingroup Z_SRTP
* @{
*/
#include <crypto/hmac.h>
#include <cryptcommon/macSkein.h>
class SrtpSymCrypto;
/**
* The implementation for a SRTCP cryptographic context.
*
* This class holds data and provides functions that implement a
* cryptographic context for SRTCP, Refer to RFC 3711, chapter 3.2 for some
* more detailed information about the SRTCP cryptographic context.
*
* Each SRTCP cryptographic context maintains a RTCP source identified by
* its SSRC. Thus you can independently protect each source inside a RTP
* session.
*
* Key management mechanisms negotiate the parameters for the SRTCP
* cryptographic context, such as master key, key length, authentication
* length and so on. The key management mechanisms are not part of
* SRTCP. Refer to MIKEY (RFC 3880) or to Phil Zimmermann's ZRTP protocol
* (RFC6189). After key management negotiated the data the application
* can setup the SRTCP cryptographic context and enable SRTCP processing.
*
* @sa CryptoContext
*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*/
class CryptoContextCtrl {
public:
/**
* @brief Constructor for an active SRTCP cryptographic context.
*
* This constructor creates an active SRTCP cryptographic context were
* algorithms are enabled, keys are computed and so on. This SRTCP
* cryptographic context can protect a RTCP SSRC stream.
*
* See the notes in CryptoContext documentation regarding the handling
* of key data.
*
* @param ssrc
* The RTP SSRC that this SRTCP cryptographic context protects.
*
* @param ealg
* The encryption algorithm to use. Possible values are <code>
* SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8,
* </code>. See chapter 4.1.1 for AESCM (Counter mode) and 4.1.2
* for AES F8 mode.
*
* @param aalg
* The authentication algorithm to use. Possible values are <code>
* SrtpEncryptionNull, SrtpAuthenticationSha1Hmac, SrtpAuthenticationSkeinHmac
* </code>.
*
* @param masterKey
* Pointer to the master key for this SRTCP cryptographic context.
* Must point to <code>masterKeyLength</code> bytes. Refer to chapter
* 3.2.1 of the RFC about the role of the master key.
*
* @param masterKeyLength
* The length in bytes of the master key in bytes. The length must
* match the selected encryption algorithm. Because SRTCP uses AES
* based encryption only, then master key length may be 16 or 32
* bytes (128 or 256 bit master key)
*
* @param masterSalt
* SRTCP uses the master salt to computer the initialization vector
* that in turn is input to compute the session key, session
* authentication key and the session salt.
*
* @param masterSaltLength
* The length in bytes of the master salt data in bytes. SRTCP uses
* AES as encryption algorithm. AES encrypts 16 byte blocks
* (independent of the key length). According to RFC3711 the standard
* value for the master salt length should be 112 bit (14 bytes).
*
* @param ekeyl
* The length in bytes of the session encryption key that SRTCP shall
* compute and use. Usually the same length as for the master key
* length. But you may use a different length as well. Be carefull
* that the key management mechanisms supports different key lengths.
*
* @param akeyl
* The length in bytes of the session authentication key. SRTCP
* computes this key and uses it as input to the authentication
* algorithm.
* The standard value is 160 bits (20 bytes).
*
* @param skeyl
* The length in bytes of the session salt. SRTCP computes this salt
* key and uses it as input during encryption. The length usually
* is the same as the master salt length.
*
* @param tagLength
* The length is bytes of the authentication tag that SRTCP appends
* to the RTP packet. Refer to chapter 4.2. in the RFC 3711.
*/
CryptoContextCtrl(uint32_t ssrc,
const int32_t ealg,
const int32_t aalg,
uint8_t* masterKey,
int32_t masterKeyLength,
uint8_t* masterSalt,
int32_t masterSaltLength,
int32_t ekeyl,
int32_t akeyl,
int32_t skeyl,
int32_t tagLength);
/**
* @brief Destructor.
*
* Cleans the SRTCP cryptographic context.
*/
~CryptoContextCtrl();
/**
* @brief Perform SRTCP encryption.
*
* This method encrypts <em>and</em> decrypts SRTCP payload data. Plain
* data gets encrypted, encrypted data get decrypted.
*
* @param rtp
* The RTP packet that contains the data to encrypt.
*
* @param len
* Length of the RTCP packet
*
* @param index
* The 31 bit SRTCP packet index.
*
* @param ssrc
* The RTCP SSRC data in <em>host</em> order.
*/
void srtcpEncrypt(uint8_t* rtp, int32_t len, uint32_t index, uint32_t ssrc);
/**
* @brief Compute the authentication tag.
*
* Compute the authentication tag according the the paramters in the
* SRTCP Cryptograhic context.
*
* @param rtp
* The RTCP packet that contains the data to authenticate.
*
* @param len
* Length of the RTCP packet
*
* @param index
* The 31 bit SRTCP index.
*
* @param tag
* Points to a buffer that hold the computed tag. This buffer must
* be able to hold <code>tagLength</code> bytes.
*/
void srtcpAuthenticate(uint8_t* rtp, int32_t len, uint32_t index, uint8_t* tag);
/**
* @brief Perform key derivation according to SRTCP specification
*
* This method computes the session key, session authentication key and the
* session salt key. This method must be called at least once after the
* SRTCP cryptograhic context was set up.
*
* This method clears the key data once it was processed by the encryptions'
* set key functions.
*
*/
void deriveSrtcpKeys();
/**
* @brief Check for packet replay.
*
* The method check if a received packet is either to old or was already
* received.
*
* The method supports a 64 packet history relative the the given
* sequence number.
*
* @param newSeqNumber
* The sequence number of the received RTCP packet in host order.
*
* @return <code>true</code> if no replay, <code>false</code> if packet
* is too old ar was already received.
*/
bool checkReplay(uint32_t newSeqNumber);
/**
* @brief Update the SRTCP packet index.
*
* Call this method after all checks were successful. See chapter
* 3.3.1 in the RFC when to update the ROC and ROC processing.
*
* @param newSeqNumber
* The sequence number of the received RTCP packet in host order.
*/
void update(uint32_t newSeqNumber);
/**
* @brief Get the length of the SRTCP authentication tag in bytes.
*
* @return the length of the authentication tag.
*/
inline int32_t getTagLength() const { return tagLength; }
/**
* @brief Get the length of the MKI in bytes.
*
* @return the length of the MKI.
*/
inline int32_t getMkiLength() const { return mkiLength; }
/**
* @brief Get the SSRC of this SRTCP Cryptograhic context.
*
* @return the SSRC.
*/
inline uint32_t getSsrc() const { return ssrcCtx; }
/**
* @brief Get the SRTCP index field of this SRTCP Cryptograhic context.
*
* @return the SRTCP.
*/
uint32_t getSrtcpIndex() const { return srtcpIndex; }
/**
* @brief Set the SRTCP index field of this SRTCP Cryptograhic context.
*
* @param index the new SRTCP index value.
*
*/
void setSrtcpIndex(uint32_t index) { srtcpIndex = index; }
/**
* @brief Set the start (base) number to compute the PRF labels.
*
* Refer to RFC3711, chapters 4.3.1 and 4.3.2 about values for labels.
* CryptoContextCtrl computes the labes as follows:
*
* - labelBase + 0 -> encryption label
* - labelBase + 1 -> authentication label
* - labelBase + 2 -> salting key label
*
* The CryptoContextCtrl constructor initializes CryptoContextCtrl#labelBase
* with 3 to comply with RFC 3711 label values.
*
* Applications may set #labelBase to other values to use CryptoContextCtrl
* for other purposes.
*/
void setLabelbase(uint8_t base) { labelBase = base; }
/**
* @brief Derive a new Crypto Context for use with a new SSRC
*
* This method returns a new CryptoContextCtrl initialized with the data
* of this crypto context. The application can use this CryptoContextCtrl
* instance to encrypt / decrypt a new stream (Synchronization source) inside
* one RTCP session.
*
* Before the application can use this crypto context it must call deriveSrtcpKeys().
*
* @param ssrc
* The SSRC for this context
*
* @return
* a new CryptoContextCtrl with all relevant data set.
*/
CryptoContextCtrl* newCryptoContextForSSRC(uint32_t ssrc);
private:
-
- typedef union _hmacCtx {
- SkeinCtx_t hmacSkeinCtx;
- hmacSha1Context hmacSha1Ctx;
- } HmacCtx;
-
uint32_t ssrcCtx;
uint32_t mkiLength;
uint8_t* mki;
uint32_t s_l;
/* bitmask for replay check */
uint64_t replay_window;
uint8_t* master_key;
uint32_t master_key_length;
uint8_t* master_salt;
uint32_t master_salt_length;
/* Session Encryption, Authentication keys, Salt */
int32_t n_e;
uint8_t* k_e;
int32_t n_a;
uint8_t* k_a;
int32_t n_s;
uint8_t* k_s;
int32_t ealg;
int32_t aalg;
int32_t ekeyl;
int32_t akeyl;
int32_t skeyl;
int32_t tagLength;
uint32_t srtcpIndex;
uint8_t labelBase;
- void* macCtx;
- HmacCtx hmacCtx;
+ void* macCtx;
SrtpSymCrypto* cipher;
SrtpSymCrypto* f8Cipher;
};
/**
* @}
*/
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 5:49 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3408877
Default Alt Text
(58 KB)
Attached To
Mode
rPYNSIPSIMPLE python3-sipsimple
Attached
Detach File
Event Timeline
Log In to Comment