You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-android/jni/redphone/SrtpStream.cpp

98 lines
2.8 KiB
C++

#include "SrtpStream.h"
#include <android/log.h>
#include <unistd.h>
#define AES_BLOCK_SIZE 16
#define TAG "SrtpStream"
SrtpStream::SrtpStream(SrtpStreamParameters *parameters) :
parameters(parameters)
{}
SrtpStream::~SrtpStream() {
if (parameters != NULL) {
delete parameters;
}
}
int SrtpStream::init() {
if (AES_set_encrypt_key(parameters->cipherKey, SRTP_AES_KEY_SIZE * 8, &key) != 0) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Failed to set AES key!");
return -1;
}
return 0;
}
void SrtpStream::setIv(int64_t logicalSequence, uint32_t ssrc, uint8_t *salt, uint8_t *iv) {
memset(iv, 0, AES_BLOCK_SIZE);
memcpy(iv, salt, SRTP_SALT_SIZE);
iv[6] ^= (uint8_t)(ssrc >> 8);
iv[7] ^= (uint8_t)(ssrc);
iv[8] ^= (uint8_t)(logicalSequence >> 40);
iv[9] ^= (uint8_t)(logicalSequence >> 32);
iv[10] ^= (uint8_t)(logicalSequence >> 24);
iv[11] ^= (uint8_t)(logicalSequence >> 16);
iv[12] ^= (uint8_t)(logicalSequence >> 8);
iv[13] ^= (uint8_t)(logicalSequence);
}
int SrtpStream::decrypt(RtpPacket &packet, int64_t logicalSequence) {
uint8_t iv[AES_BLOCK_SIZE];
uint8_t ecount[AES_BLOCK_SIZE];
uint8_t ourMac[SRTP_MAC_SIZE];
uint32_t num = 0;
uint32_t digest = 0;
setIv(logicalSequence, packet.getSsrc(), parameters->salt, iv);
memset(ecount, 0, sizeof(ecount));
if (packet.getPayloadLen() < (SRTP_MAC_SIZE + 1)) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Packet shorter than MAC!");
return -1;
}
HMAC(EVP_sha1(), parameters->macKey, SRTP_MAC_KEY_SIZE,
(uint8_t*)packet.getSerializedPacket(), packet.getSerializedPacketLen() - SRTP_MAC_SIZE, ourMac, &digest);
if (memcmp(ourMac, packet.getSerializedPacket() + packet.getSerializedPacketLen() - SRTP_MAC_SIZE,
SRTP_MAC_SIZE) != 0)
{
__android_log_print(ANDROID_LOG_WARN, TAG, "MAC comparison failed!");
return -1;
}
packet.setPayloadLen(packet.getPayloadLen() - SRTP_MAC_SIZE);
AES_ctr128_encrypt((uint8_t*)packet.getPayload(), (uint8_t*)packet.getPayload(),
packet.getPayloadLen(), &key, iv, ecount, &num);
return 0;
}
int SrtpStream::encrypt(RtpPacket &packet, int64_t logicalSequence) {
uint8_t iv[AES_BLOCK_SIZE];
uint8_t ecount[AES_BLOCK_SIZE];
uint32_t num = 0;
uint32_t digest = 0;
setIv(logicalSequence, packet.getSsrc(), parameters->salt, iv);
memset(ecount, 0, sizeof(ecount));
AES_ctr128_encrypt((uint8_t*)packet.getPayload(), (uint8_t*)packet.getPayload(), packet.getPayloadLen(), &key, iv, ecount, &num);
HMAC(EVP_sha1(), parameters->macKey, SRTP_MAC_KEY_SIZE,
(uint8_t*)packet.getSerializedPacket(), packet.getSerializedPacketLen(),
(uint8_t*)packet.getSerializedPacket() + packet.getSerializedPacketLen(), &digest);
packet.setPayloadLen(packet.getPayloadLen() + SRTP_MAC_SIZE);
return 0;
}