summaryrefslogtreecommitdiff
path: root/src/srtp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/srtp.cc')
-rw-r--r--src/srtp.cc230
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;
+}