diff options
Diffstat (limited to 'src/srtp.cc')
-rw-r--r-- | src/srtp.cc | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/srtp.cc b/src/srtp.cc new file mode 100644 index 0000000..98c4002 --- /dev/null +++ b/src/srtp.cc @@ -0,0 +1,230 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * srtp.cc + * + * Thu Sep 5 10:46:10 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of lrtp. + * + * lrtp 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. + * + * lrtp 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 lrtp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "srtp.h" + +#ifdef WIN32 +#include <srtp/crypto/include/datatypes.h> +#include <srtp/include/srtp.h> +#include <srtp/include/rtp_priv.h> +#else +#include <srtp/datatypes.h> +#include <srtp/srtp.h> +#include <srtp/rtp_priv.h> +#endif + +#include "asc2bin.h" + +struct SRTP::prv { + char *key; + size_t key_len; + + unsigned int ssrc; + + srtp_t session; + srtp_policy_t policy; +}; + +static bool is_initialised = false; + +SRTP::SRTP(std::string key, unsigned int ssrc) +{ + prv = NULL; + + err_status_t status; + + if(!is_initialised) { + status = srtp_init(); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_init failed %d\n", status); + } + is_initialised = true; + } + + prv = new struct prv; + + prv->ssrc = ssrc; + + setupKey(key); + setupPolicy(true, true); + + status = srtp_create(&prv->session, &prv->policy); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_create %d\n", status); + } + + status = srtp_add_stream(prv->session, &prv->policy); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_add_stream %d\n", status); + } +} + +SRTP::~SRTP() +{ + err_status_t status = srtp_remove_stream(prv->session, htonl(prv->ssrc)); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_remove_stream failed %d\n", status); + } + + status = srtp_dealloc(prv->session); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_dealloc failed %d\n", status); + } + + status = srtp_shutdown(); + if(status != err_status_ok) { + // TODO: Error handling + printf("srtp_shutdown failed %d\n", status); + } + + is_initialised = false; + + if(prv) { + free(prv->key); + delete prv; + } +} + +void SRTP::setupKey(const std::string &key) +{ + prv->key = (char *)calloc(MASTER_KEY_LEN, 1); + prv->key_len = MASTER_KEY_LEN; + + if(key.length() > MASTER_KEY_LEN * 2) printf("KeyTooLong\n"); // TODO + + // Read key from hexadecimal on command line into an octet string + ssize_t len = asc2bin(prv->key, prv->key_len, key.c_str(), key.size()); + + if(len == -1) printf("InvalidHexKeyString\n"); // TODO + prv->key_len = len; + + // check that hex string is the right length. + if(len < MASTER_KEY_LEN) printf("KeyTooShort\n"); // TODO +} + +void SRTP::setupPolicy(bool confidentiality, bool authentication) +{ +#ifndef USE_CRYPTO + confidentiality = authentication = false; + printf("No crypto!\n") +#endif + + /* + * create policy structure, using the default mechanisms but + * with only the security services requested on the command line, + * using the right SSRC value + */ + if(confidentiality && authentication) { + crypto_policy_set_aes_cm_128_hmac_sha1_80(&prv->policy.rtp); + prv->policy.rtp.sec_serv = sec_serv_conf_and_auth; + } else if(confidentiality && !authentication) { + crypto_policy_set_aes_cm_128_null_auth(&prv->policy.rtp); + prv->policy.rtp.sec_serv = sec_serv_conf; + } else if(!confidentiality && authentication) { + crypto_policy_set_null_cipher_hmac_sha1_80(&prv->policy.rtp); + prv->policy.rtp.sec_serv = sec_serv_auth; + } else { + /* + * we're not providing security services, so set the policy to the + * null policy + * + * Note that this policy does not conform to the SRTP + * specification, since RTCP authentication is required. However, + * the effect of this policy is to turn off SRTP, so that this + * application is now a vanilla-flavored RTP application. + */ + prv->policy.rtp.cipher_type = NULL_CIPHER; + prv->policy.rtp.cipher_key_len = 0; + prv->policy.rtp.auth_type = NULL_AUTH; + prv->policy.rtp.auth_key_len = 0; + prv->policy.rtp.auth_tag_len = 0; + prv->policy.rtp.sec_serv = sec_serv_none; + } + + crypto_policy_set_rtcp_default(&prv->policy.rtcp); + prv->policy.rtcp.sec_serv = sec_serv_none; // No need for RTCP + + prv->policy.key = (uint8_t *)prv->key; + prv->policy.ssrc.type = ssrc_specific; + prv->policy.ssrc.value = prv->ssrc; + prv->policy.next = NULL; +} + +int SRTP::encrypt(char *packet, size_t size) +{ + int sz = size; + err_status_t status = srtp_protect(prv->session, packet, &sz); + if(status != err_status_ok) { + // TODO: throw SRTP::UnprotectException(); + printf("srtp_protect failed %d\n", status); + } + + return sz; +} + +int SRTP::decrypt(char *packet, size_t size) +{ + int sz = size; + err_status_t status = srtp_unprotect(prv->session, packet, &sz); + switch(status) { + case err_status_ok: + // No errors. + break; + case err_status_replay_fail: + // TODO: throw SRTP::ReplayException();// (replay check failed) + printf("srtp_unprotect failed replay %d\n", status); + break; + case err_status_replay_old: + // TODO: throw SRTP::ReplayOldException();// (replay check failed) + printf("srtp_unprotect failed replay_old %d\n", status); + break; + case err_status_auth_fail: + // TODO: throw SRTP::AuthCheckException();// (auth check failed) + printf("srtp_unprotect failed auth %d\n", status); + break; + default: + // TODO: throw SRTP::UnprotectException(); + printf("srtp_unprotect failed %d\n", status); + break; + } + + /* + if(octets_recvd - RTP_HEADER_LEN > (ssize_t)size) { + printf("BufferSize %d\n", status); + } + */ + + // TODO: rtp.fromBuffer(packet, size); + //memcpy(buf, prv->receiver->message.body, octets_recvd - RTP_HEADER_LEN); + + return sz; +} |