Page MenuHomePhabricator

No OneTemporary

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

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)

Event Timeline