uvgrtp-base/include/srtp.hh

182 lines
6.2 KiB
C++

#pragma once
#ifdef _WIN32
#include <winsock2.h>
#include <mswsock.h>
#include <inaddr.h>
#else
#include <netinet/ip.h>
#include <arpa/inet.h>
#endif
#include <cstdint>
#include "debug.hh"
#include "frame.hh"
#include "rtp.hh"
#include "util.hh"
#ifdef __RTP_CRYPTO__
#include "zrtp.hh"
#endif
#define AES_KEY_LENGTH 16 /* 128 bits */
#define HMAC_KEY_LENGTH 32 /* 256 bits */
#define SALT_LENGTH 14 /* 112 bits */
namespace uvg_rtp {
enum STYPE {
SRTP = 0,
SRTCP = 1
};
enum ETYPE {
AES_128 = 0,
};
enum HTYPE {
HMAC_SHA1 = 0,
};
enum LABELS {
SRTP_ENCRYPTION = 0x0,
SRTP_AUTHENTICATION = 0x1,
SRTP_SALTING = 0x2
};
/* Key context for SRTP keys,
* ZRTP generates two keys: one for initiator and one for responder
*
* Master key is not directly used to encrypt packets but it is used
* to create session keys for the SRTP/SRTCP */
typedef struct srtp_key_ctx {
/* Keys negotiated by ZRTP */
struct {
/* Our master key and salt */
uint8_t local_key[AES_KEY_LENGTH];
uint8_t local_salt[SALT_LENGTH];
/* Remote's master key and salt */
uint8_t remote_key[AES_KEY_LENGTH];
uint8_t remote_salt[SALT_LENGTH];
} master;
/* Used to encrypt/authenticate packets sent by us */
struct {
uint8_t enc_key[AES_KEY_LENGTH];
uint8_t auth_key[AES_KEY_LENGTH];
uint8_t salt_key[SALT_LENGTH];
} local;
/* Used to decrypt/Authenticate packets sent by remote */
struct {
uint8_t enc_key[AES_KEY_LENGTH];
uint8_t auth_key[AES_KEY_LENGTH];
uint8_t salt_key[SALT_LENGTH];
} remote;
} srtp_key_ctx_t;
typedef struct srtp_ctx {
int type; /* srtp or srtcp */
uint32_t roc; /* roll-over counter */
int enc; /* identifier for encryption algorithm */
int hmac; /* identifier for message authentication algorithm */
bool mki_present; /* is MKI present in SRTP packets */
size_t mki_size; /* length of the MKI field in bytes if it's present */
uint8_t *mki; /* master key identifier */
uint8_t *master_key; /* master key */
uint8_t *master_salt; /* master salt */
size_t mk_cnt; /* how many packets have been encrypted with master key */
size_t n_e; /* size of encryption key */
size_t n_a; /* size of hmac key */
/* following fields are receiver-only */
uint16_t s_l; /* highest received sequence number */
uint8_t *replay; /* list of recently received and authenticated SRTP packets */
} srtp_ctx_t;
class srtp {
public:
srtp();
~srtp();
#ifdef __RTP_CRYPTO__
/* Setup Secure RTP/RTCP connection using ZRTP
*
* Return RTP_OK if SRTP setup was successful
* Return RTP_INVALID_VALUE if "zrtp" is nullptr
* Return RTP_MEMORY allocation failed */
rtp_error_t init_zrtp(int type, int flags, uvg_rtp::rtp *rtp, uvg_rtp::zrtp *zrtp);
/* Setup Secure RTP/RTCP connection using user-managed keys
*
* Length of "key" must be AES_KEY_LENGTH (16 bytes)
* Length of "salt" must be SALT_LENGTH (14 bytes)
*
* Return RTP_OK if SRTP setup was successful
* Return RTP_INVALID_VALUE if "key" or "salt" is nullptr
* Return RTP_MEMORY allocation failed */
rtp_error_t init_user(int type, int flags, uint8_t *key, uint8_t *salt);
/* Encrypt the payload of "frame" using the private session key
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "frame" is nullptr
* Return RTP_NOT_INITIALIZED if SRTP has not been initialized */
rtp_error_t encrypt(uvg_rtp::frame::rtp_frame *frame);
/* Encrypt the payload of "buffers" vector using the private session key
* The payload that is encrypted is the last buffer of "buffers" and the
* RTP header is the first" buffer of "buffers"
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "frame" is nullptr
* Return RTP_NOT_INITIALIZED if SRTP has not been initialized */
rtp_error_t encrypt(std::vector<std::pair<size_t, uint8_t *>>& buffers);
/* Decrypt the payload payload of "frame" using the private session key
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "frame" is nullptr
* Return RTP_NOT_INITIALIZED if SRTP has not been initialized */
rtp_error_t decrypt(uint8_t *buffer, size_t len);
/* Authenticate "frame" using the private session key
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "frame" is nullptr or if authentication failed */
rtp_error_t authenticate(uvg_rtp::frame::rtp_frame *frame);
#endif
private:
#ifdef __RTP_CRYPTO__
rtp_error_t derive_key(int label, uint8_t *key, uint8_t *salt, uint8_t *out, size_t len);
/* Create IV for the packet that is about to be encrypted
*
* Return RTP_OK on success and place the iv to "out"
* Return RTP_INVALID_VALUE if one of the parameters is invalid */
rtp_error_t create_iv(uint8_t *out, uint32_t ssrc, uint64_t index, uint8_t *salt);
/* Internal encrypt method that takes only the necessary variables and encrypts "buffer" */
rtp_error_t __encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len);
/* Internal init method that initialize the SRTP context using values in key_ctx_.master */
rtp_error_t __init(int type, int flags);
#endif
srtp_key_ctx_t key_ctx_;
srtp_ctx_t srtp_ctx_;
/* If NULL cipher is enabled, it means that RTP packets are not
* encrypted but other security mechanisms described in RFC 3711 may be used */
bool use_null_cipher_;
};
};