* #40116: Add zrtp related files, update libzrtpcpp
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
index 7d36f2b..d7d2265 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
@@ -1,13 +1,107 @@
+/*
+ Copyright (C) 2012-2013 Werner Dittmann
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPSDESSTREAM_H_
+#define _ZRTPSDESSTREAM_H_
+/**
+ * @file ZrtpSdesStream.h
+ * @brief The ZRTP main engine
+ * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation
+ * @{
+ *
+ * This class implements SDES and provides a simple to use API for applications.
+ *
+ * This SDES implementation currently supports only two SDES algorithms and it does
+ * not support optional parameters such as lifetime or MKI parameters. Also session
+ * parameters are not supported. Most applications that use SDES don't use these
+ * optional parameters.
+ *
+ * It is not necessary to explicitly start the SDES stream. The class initiates
+ * the SRTP after it created and parsed all necessary SDES crypto strings.
+ *
+ * Because SDES works together with the signaling protocol, for example SIP, it is
+ * important to adhere to a defined flow. The following pseudo code snippet depicts
+ * such a flow. Applications shall follow this flow.
+ *
+ *<pre>
+ *
+ * Inviter Answerer
+ * (Offerer)
+ *
+ * ZrtpSdesStream inv; ZrtpSdesStream answ;
+ *
+ * // create/get own SDES data
+ * inv.createSdes(...);
+ * inv.getCryptoMixAttribute(...)
+ *
+ * // prepare SIP/SDP offer, send
+ * // it to answerer
+ * // receive SIP/SDP, get
+ * // SDES data, parse/set it
+ * answ.setCryptoMixAttribute(...)
+ * answ.parseSdes(...)
+ *
+ * // create/get own SDES data
+ * answ.getCryptoMixAttribute(...)
+ * answ.createSdes(...)
+ *
+ * // prepare SIP/SDP answer,
+ * // send to offerer
+ * // receive SIP/SDP answer, get
+ * // SDES data, parse, set mix algo
+ * // if availabe
+ * inv.setCryptoMixAttribute(...)
+ * inv.parseSdes(...)
+ *
+ * ... ...
+ *
+ * inv.outgoingRtp(...)
+ * answ.incomingRtp(...)
+ *
+ * answ.outgoingRtp(...)
+ * inv.incomingRtp(...)
+ *</pre>
+ *
+ * To use SDES without the new crypto mix feature just do not use the crypto mix functions.
+ * An application may always send crypto mix attributes. If the answerer does not support this
+ * feature it does not send back a selected algorithm and the offerer cannot set an algorithm.
+ * Thus the crypto mix feature is not used.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <common/osSpecifics.h>
class CryptoContext;
class CryptoContextCtrl;
+/*
+ * These functions support 256 bit encryption algorithms.
+ */
+#define MAX_KEY_LEN 32
+#define MAX_SALT_LEN 14
+#define MAX_DIGEST_LENGTH 64
+
/**
* Maximum length of a raw crypto string.
*/
#define MAX_CRYPT_STRING_LEN 200
-class ZrtpSdesStream {
+class __EXPORT ZrtpSdesStream {
public:
@@ -15,12 +109,12 @@
* Supported SDES crypto suites.
*/
typedef enum {
- AES_CM_128_HMAC_SHA1_32 = 1,
+ AES_CM_128_HMAC_SHA1_32 = 0,
AES_CM_128_HMAC_SHA1_80
} sdesSuites;
/**
- * SDES stream stated
+ * SDES stream state
*/
typedef enum {
STREAM_INITALIZED = 1,
@@ -29,15 +123,18 @@
SDES_SRTP_ACTIVE
} sdesZrtpStates;
+ typedef enum {
+ MIX_NONE = 0,
+ MIX_HMAC_SHA,
+ MIX_MAC_SKEIN
+ } sdesHmacTypeMix;
+
/**
* @brief Create and SDES/ZRTP stream.
*
* This method creates an SDES stream with capabilities to handle RTP,
* RTCP, SRTP, and SRTCP packets.
*
- * It is not necessary to explicitly start the SDES stream. The method initiates
- * the SRTP after it created and parsed all necessary SDES crypto strings.
- *
* @param suite defines which crypto suite to use for this stream. The values are
* @c AES_CM_128_HMAC_SHA1_80 or @c AES_CM_128_HMAC_SHA1_32.
*/
@@ -67,19 +164,16 @@
* @c zrtp-hash from the SDP parameters and forwards it to @c libzrtp. The
* answering application's SRTP environment is now ready.
*
- * @param cryptoString points to a char output buffer that receives the
- * crypto string in the raw format, without the any
- * signaling prefix, for example @c a=crypto: in case
- * of SDP signaling. The function terminates the
- * crypto string with a @c nul byte
+ * @param cryptoString output buffer that receives the crypto string in raw
+ * format, without the any signaling prefix, for example
+ * @c a=crypto:. The function terminates the crypto string
+ * with a @c nul byte
*
* @param maxLen length of the crypto string buffer. On return it contains the
* actual length of the crypto string.
*
- * @param sipInvite if this is set to @c true (not zero) then the method
- * takes the necessary actions to create the crypto eonvironment
- * for the inviting SIP application. It it is zero then it handles
- * the invited case (answerer).
+ * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must
+ * set it to @c false.
*
* @return @c true if data could be created, @c false otherwise.
*/
@@ -88,36 +182,67 @@
/**
* @brief Parses an SDES crypto string for the SDES/ZRTP stream.
*
- * Parses a received crypto string that the application received in a SIP INVITE
+ * Parses a SDES crypto string that the application received in a SIP INVITE
* or SIP 200 OK.
*
- * An INVITE-ing application shall call this function right after it received
+ * An INVITE-ing (offerer) application shall call this function right after it received
* the 200 OK from the answering application and must call this function with the
- * @c sipInvite parameter set to @c true. This usually at the same point when
- * it gets the @c zrtp-hash from the SDP parameters.
- * This application's SRTP environment is now ready.
+ * @c sipInvite parameter set to @c true. The offerer's SRTP is now ready for use.
*
* The answering application calls this function after it received the INVITE and
* extracted the crypto string from the SDP and must call this function with the
- * @c sipInvite parameter set to @c false. This is usually the same point when
- * it gets the @c zrtp-hash from the SDP parameters.
+ * @c sipInvite parameter set to @c false.
*
- * @param cryptoString points to the crypto sting in raw format,
- * without any signaling prefix, for example @c
- * a=crypto: in case of SDP signaling.
+ * @param cryptoString the received crypto sting in raw format,
+ * without any signaling prefix, for example @c a=crypto:
*
* @param length length of the crypto string to parse. If the length is
* @c zero then the function uses @c strlen to compute
* the length.
*
- * @param sipInvite if this is set to @c true then the method
- * takes the necessary actions to create the crypto eonvironment
- * for the inviting SIP application. It it is zero then it handles
- * the invited case (answerer).
+ * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must
+ * set it to @c false.
*
* @return @c true if data could be created, @c false otherwise.
*/
- bool parseSdes(char *cryptoString, size_t length, bool sipInvite);
+ bool parseSdes(const char *cryptoString, size_t length, bool sipInvite);
+
+ /**
+ * @brief Get Crypto Mix attribute string
+ *
+ * The offerer calls this method to get a string of @b all supported crypto mix algorithms
+ * and shall send this list to the answerer.
+ *
+ * The answerer calls this function only @b after it received the crypto mix string and @b after
+ * calling @c setCryptoMixAttribute(...). The method returns only one (the selected)
+ * crypto mix algorithm and the answerer must send this to the offerer, for example in 200 OK.
+ *
+ * @param algoNames buffer to store the nul terminated crypto mix algorithm names.
+ * The buffer must be long enough to hold at least the name of the mandatory
+ * algorithm HMAC-SHA-384.
+ *
+ * @param length length of buffer
+ *
+ * @return Length of algorithm names (excluding nul byte) or zero if crypto mix not supported or
+ * enabled.
+ */
+ int getCryptoMixAttribute(char *algoNames, size_t length);
+
+ /**
+ * @brief Set Crypto Mix attribute string
+ *
+ * The method checks if it the string contains an supported algorithm and selects one algorithm.
+ *
+ * The offerer calls this method @b after it received the selected algorithm in the answer.
+ *
+ * The answerer must call this method @b before it calls the @c getCryptoMixAttribute() method.
+ *
+ * @param algoNames buffer that contains the received crypto mix algorithm names.
+ * The buffer must be nul terminated.
+ *
+ * @return @c false if none of the offered algorithms is supported.
+ */
+ bool setCryptoMixAttribute(const char *algoNames);
/*
* ******** Outgoing RTP/RTCP packet handling
@@ -151,7 +276,7 @@
/**
* @brief Process an outgoing RTCP packet
*
- * This function works in the same way as @c sdesZrtpProcessRtp.
+ * This function works in the same way as @c outgoingRtp.
*
* @param packet the buffer that contains the RTCP packet. After processing, the
* encrypted packet is stored in the same buffer. The buffer must
@@ -185,7 +310,7 @@
* @param packet the buffer that contains the RTP/SRTP packet. After processing,
* the decrypted packet is stored in the same buffer.
*
- * @param length length of the RTCP packet
+ * @param length length of the RTP packet
*
* @param newLength to an integer that get the new length of the packet excluding SRTCP data.
*
@@ -199,7 +324,7 @@
/**
* @brief Process an incoming RTCP or SRTCP packet
*
- * This function works in the same way as @c sdesZrtpProcessSrtp.
+ * This function works in the same way as @c incomingRtp.
*
* @param packet the buffer that contains the RTCP/SRTCP packet. After processing,
* the decrypted packet is stored in the same buffer.
@@ -216,21 +341,64 @@
int incomingSrtcp(uint8_t *packet, size_t length, size_t *newLength);
/**
- * Return state of SDES stream.
+ * @brief Process an outgoing ZRTP packet.
+ *
+ * Works like @c outgoingRtp, refer to that documentation.
+ *
+ * @param packet the buffer that contains the ZRTP packet.
+ *
+ * @param length length of the ZRTP packet
+ *
+ * @param newLength to an integer that get the new length of the packet including SRTP data.
+ *
+ * @return
+ * - @c true if encryption is successful, app shall send packet to the recipient.
+ * - @c false if there was an error during encryption, don't send the packet.
+ */
+ bool outgoingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength);
+
+ /**
+ * @brief Process an incoming ZRTP packet
+ *
+ * Works like @c incomingRtp, refer to that documentation.
+ *
+ * @param packet the buffer that contains the ZRTP/SRTP packet. After processing,
+ * the decrypted packet is stored in the same buffer.
+ *
+ * @param length length of the RTP packet
+ *
+ * @param newLength to an integer that get the new length of the packet excluding SRTCP data.
+ *
+ * @return
+ * - 1: success,
+ * - -1: SRTP authentication failed,
+ * - -2: SRTP replay check failed
+ */
+ int incomingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength);
+
+ /**
+ * @brief Return state of SDES stream.
*
* @return state of stream.
*/
sdesZrtpStates getState() {return state;}
/**
- * Return name of active cipher algorithm.
+ * @brief Return SDES crypto mixer HMAC type.
+ *
+ * @return HMAC type
+ */
+ sdesHmacTypeMix getHmacTypeMix() {return cryptoMixHashType;}
+
+ /**
+ * @brief Return name of active cipher algorithm.
*
* @return point to name of cipher algorithm.
*/
const char* getCipher();
/**
- * Return name of active SRTP authentication algorithm.
+ * @brief Return name of active SRTP authentication algorithm.
*
* @return point to name of authentication algorithm.
*/
@@ -244,11 +412,9 @@
/**
* @brief Create an SRTP crypto context and the according SDES crypto string.
*
- * This lower layer method creates an SRTP profile an the according SDES
- * crypto string. It selects a valid crypto suite, generates the key and salt
- * data, converts these into base 64 and returns the crypto string in raw format
- * without any signaling prefixes. The method also creates the internal
- * SRTP/SRTCP crypto contexts for outgoing data.
+ * This lower layer method creates an SDES crypto string. It selects a valid
+ * crypto suite, generates the key and salt data, converts these into base 64
+ * and returns the crypto string in raw format without any signaling prefixes.
*
* The output string has the following format:
* @verbatim
@@ -291,8 +457,7 @@
*
* The method parses an offered SDES crypto string and checks if it is
* valid. Next it checks if the string contains a supported crypto suite
- * and if the key and salt lengths match the selected crypto suite. The method
- * also creates the internal SRTP/SRTCP crypto contexts for incoming data.
+ * and if the key and salt lengths match the selected crypto suite.
*
* Applications usually don't use this method directly. Applications shall
* use the SDES stream functions.
@@ -324,6 +489,28 @@
*/
bool parseCreateSdesProfile(const char *cryptoString, size_t length, sdesSuites *parsedSuite, int32_t *tag);
+ /**
+ * @brief Create the SRTP contexts after all SDES creation and parsing is done.
+ *
+ * @param sipInvite if this is set to @c true (not zero) then the method
+ * computes the key data for the inviting SIP application (offerer) and
+ * for the answerer otherwise.
+ */
+ void createSrtpContexts(bool sipInvite);
+
+ /**
+ * @brief Compute the mixed keys if SDES mixing attribute is set.
+ *
+ * The method takes the parsed or created SDES key material and computes the mixed keys and salt.
+ * It replaces the existing key material with the new data.
+ *
+ * @param sipInvite if this is set to @c true (not zero) then the method
+ * computes the key data for the inviting SIP application (offerer) and
+ * for the answerer otherwise.
+ */
+ void computeMixedKeys(bool sipInvite);
+
+
sdesZrtpStates state;
sdesSuites suite;
int32_t tag;
@@ -333,4 +520,28 @@
CryptoContextCtrl *sendSrtcp; //!< The SRTCP context for this stream
uint32_t srtcpIndex; //!< the local SRTCP index
+ CryptoContext *recvZrtpTunnel; //!< The SRTP context for sender ZRTP tunnel
+ CryptoContext *sendZrtpTunnel; //!< The SRTP context for receiver ZRTP tunnel
+
+ int32_t cryptoMixHashLength;
+ sdesHmacTypeMix cryptoMixHashType;
+
+ // Variables for crypto that this client creates and sends to the other client, filled during SDES create
+ uint8_t localKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4]; //!< Some buffer for key and salt, multiple of 4
+ int localKeyLenBytes;
+ int localSaltLenBytes;
+ int localCipher;
+ int localAuthn;
+ int localAuthKeyLen;
+ int localTagLength;
+
+ // Variables for crypto that this client receives from the other client, filled during SDES parse
+ uint8_t remoteKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4]; //!< Some buffer for key and salt, multiple of 4
+ int remoteKeyLenBytes;
+ int remoteSaltLenBytes;
+ int remoteCipher;
+ int remoteAuthn;
+ int remoteAuthKeyLen;
+ int remoteTagLength;
};
+#endif
\ No newline at end of file