* #35924 (zrtp): switch to libzrtpcpp
diff --git a/jni/libzrtp/sources/srtp/SrtpHandler.cpp b/jni/libzrtp/sources/srtp/SrtpHandler.cpp
new file mode 100644
index 0000000..621e25a
--- /dev/null
+++ b/jni/libzrtp/sources/srtp/SrtpHandler.cpp
@@ -0,0 +1,261 @@
+/*
+ Copyright (C) 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <common/osSpecifics.h>
+
+#include <SrtpHandler.h>
+#include <CryptoContext.h>
+#include <CryptoContextCtrl.h>
+
+#define RTP_HEADER_LENGTH 12
+
+bool SrtpHandler::decodeRtp(uint8_t* buffer, int32_t length, uint32_t *ssrc, uint16_t *seq, uint8_t** payload, int32_t *payloadlen)
+{
+ int offset;
+ uint16_t *pus;
+ uint32_t *pui;
+
+ /* Assume RTP header at the start of buffer. */
+
+ if ((*buffer & 0xC0) != 0x80) { // check version bits
+ return false;
+ }
+ if (length < RTP_HEADER_LENGTH)
+ return false;
+
+ /* Get some handy pointers */
+ pus = (uint16_t*)buffer;
+ pui = (uint32_t*)buffer;
+
+ uint16_t tmp16 = pus[1]; // get seq number
+ *seq = zrtpNtohs(tmp16); // and return in host oder
+
+ uint32_t tmp32 = pui[2]; // get SSRC
+ *ssrc = zrtpNtohl(tmp32); // and return in host order
+
+ /* Payload is located right after header plus CSRC */
+ int32_t numCC = buffer[0] & 0x0f; // lower 4 bits in first byte is num of contrib SSRC
+ offset = RTP_HEADER_LENGTH + (numCC * sizeof(uint32_t));
+
+ // Sanity check
+ if (offset > length)
+ return false;
+
+ /* Adjust payload offset if RTP extension is used. */
+ if ((*buffer & 0x10) == 0x10) { // packet contains RTP extension
+ pus = (uint16_t*)(buffer + offset); // pus points to extension as 16bit pointer
+ tmp16 = pus[1]; // the second 16 bit word is the length
+ tmp16 = zrtpNtohs(tmp16); // to host order
+ offset += (tmp16 + 1) * sizeof(uint32_t);
+ }
+ /* Sanity check */
+ if (offset > length)
+ return false;
+
+ /* Set payload and payload length. */
+ *payload = buffer + offset;
+ *payloadlen = length - offset;
+
+ return true;
+}
+
+bool SrtpHandler::protect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength)
+{
+ uint8_t* payload = NULL;
+ int32_t payloadlen = 0;
+ uint16_t seqnum;
+ uint32_t ssrc;
+
+
+ if (pcc == NULL) {
+ return false;
+ }
+ if (!decodeRtp(buffer, length, &ssrc, &seqnum, &payload, &payloadlen))
+ return false;
+
+ /* Encrypt the packet */
+ uint64_t index = ((uint64_t)pcc->getRoc() << 16) | (uint64_t)seqnum;
+
+ pcc->srtpEncrypt(buffer, payload, payloadlen, index, ssrc);
+
+ // NO MKI support yet - here we assume MKI is zero. To build in MKI
+ // take MKI length into account when storing the authentication tag.
+
+ /* Compute MAC and store at end of RTP packet data */
+ if (pcc->getTagLength() > 0) {
+ pcc->srtpAuthenticate(buffer, length, pcc->getRoc(), buffer+length);
+ }
+ *newLength = length + pcc->getTagLength();
+
+ /* Update the ROC if necessary */
+ if (seqnum == 0xFFFF ) {
+ pcc->setRoc(pcc->getRoc() + 1);
+ }
+ return true;
+}
+
+int32_t SrtpHandler::unprotect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength)
+{
+ uint8_t* payload = NULL;
+ int32_t payloadlen = 0;
+ uint16_t seqnum;
+ uint32_t ssrc;
+
+ if (pcc == NULL) {
+ return 0;
+ }
+
+ if (!decodeRtp(buffer, length, &ssrc, &seqnum, &payload, &payloadlen))
+ return 0;
+ /*
+ * This is the setting of the packet data when we come to this point:
+ *
+ * length: complete length of received data
+ * buffer: points to data as received from network
+ * payloadlen: length of data excluding hdrSize and padding
+ *
+ * Because this is an SRTP packet we need to adjust some values here.
+ * The SRTP MKI and authentication data is always at the end of a
+ * packet. Thus compute the position of this data.
+ */
+ uint32_t srtpDataIndex = length - (pcc->getTagLength() + pcc->getMkiLength());
+
+ // Compute new length
+ length -= pcc->getTagLength() + pcc->getMkiLength();
+ *newLength = length;
+
+ // recompute payloadlen by subtracting SRTP data
+ payloadlen -= pcc->getTagLength() + pcc->getMkiLength();
+
+ // MKI is unused, so just skip it
+ // const uint8* mki = buffer + srtpDataIndex;
+ uint8_t* tag = buffer + srtpDataIndex + pcc->getMkiLength();
+
+ /* Replay control */
+ if (!pcc->checkReplay(seqnum)) {
+ return -2;
+ }
+ /* Guess the index */
+ uint64_t guessedIndex = pcc->guessIndex(seqnum);
+
+ if (pcc->getTagLength() > 0) {
+ uint32_t guessedRoc = guessedIndex >> 16;
+ uint8_t mac[20];
+
+ pcc->srtpAuthenticate(buffer, (uint32_t)length, guessedRoc, mac);
+ if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
+ return -1;
+ }
+ }
+ /* Decrypt the content */
+ pcc->srtpEncrypt(buffer, payload, payloadlen, guessedIndex, ssrc);
+
+ /* Update the Crypto-context */
+ pcc->update(seqnum);
+
+ return 1;
+}
+
+
+bool SrtpHandler::protectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength)
+{
+
+ if (pcc == NULL) {
+ return false;
+ }
+ /* Encrypt the packet */
+ uint32_t ssrc = *(reinterpret_cast<uint32_t*>(buffer + 4)); // always SSRC of sender
+ ssrc = zrtpNtohl(ssrc);
+
+ uint32_t encIndex = pcc->getSrtcpIndex();
+ pcc->srtcpEncrypt(buffer + 8, length - 8, encIndex, ssrc);
+
+ encIndex |= 0x80000000; // set the E flag
+
+ // Fill SRTCP index as last word
+ uint32_t* ip = reinterpret_cast<uint32_t*>(buffer+length);
+ *ip = zrtpHtonl(encIndex);
+
+ // NO MKI support yet - here we assume MKI is zero. To build in MKI
+ // take MKI length into account when storing the authentication tag.
+
+ // Compute MAC and store in packet after the SRTCP index field
+ pcc->srtcpAuthenticate(buffer, length, encIndex, buffer + length + sizeof(uint32_t));
+
+ encIndex++;
+ encIndex &= ~0x80000000; // clear the E-flag and modulo 2^31
+ pcc->setSrtcpIndex(encIndex);
+ *newLength = length + pcc->getTagLength() + sizeof(uint32_t);
+
+ return true;
+}
+
+int32_t SrtpHandler::unprotectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength)
+{
+
+ if (pcc == NULL) {
+ return 0;
+ }
+
+ // Compute the total length of the payload
+ int32_t payloadLen = length - (pcc->getTagLength() + pcc->getMkiLength() + 4);
+ *newLength = payloadLen;
+
+ // point to the SRTCP index field just after the real payload
+ const uint32_t* index = reinterpret_cast<uint32_t*>(buffer + payloadLen);
+
+ uint32_t encIndex = zrtpNtohl(*index);
+ uint32_t remoteIndex = encIndex & ~0x80000000; // get index without Encryption flag
+
+ if (!pcc->checkReplay(remoteIndex)) {
+ return -2;
+ }
+
+ uint8_t mac[20];
+
+ // Now get a pointer to the authentication tag field
+ const uint8_t* tag = buffer + (length - pcc->getTagLength());
+
+ // Authenticate includes the index, but not MKI and not (obviously) the tag itself
+ pcc->srtcpAuthenticate(buffer, payloadLen, encIndex, mac);
+ if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
+ return -1;
+ }
+
+ uint32_t ssrc = *(reinterpret_cast<uint32_t*>(buffer + 4)); // always SSRC of sender
+ ssrc = zrtpNtohl(ssrc);
+
+ // Decrypt the content, exclude the very first SRTCP header (fixed, 8 bytes)
+ if (encIndex & 0x80000000)
+ pcc->srtcpEncrypt(buffer + 8, payloadLen - 8, remoteIndex, ssrc);
+
+ // Update the Crypto-context
+ pcc->update(remoteIndex);
+
+ return 1;
+}
+