blob: 4e03f28b4b0c5c24e9fe2b9c1664e3be1f6d9caa [file] [log] [blame]
/*
Copyright (C) 2006-2010 Werner Dittmann
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 _ZRTP_H_
#define _ZRTP_H_
/**
* @file ZRtp.h
* @brief The ZRTP main engine
* @defgroup GNU_ZRTP The GNU ZRTP C++ implementation
* @{
*/
#include <cstdlib>
#include <libzrtpcpp/ZrtpPacketHello.h>
#include <libzrtpcpp/ZrtpPacketHelloAck.h>
#include <libzrtpcpp/ZrtpPacketCommit.h>
#include <libzrtpcpp/ZrtpPacketDHPart.h>
#include <libzrtpcpp/ZrtpPacketConfirm.h>
#include <libzrtpcpp/ZrtpPacketConf2Ack.h>
#include <libzrtpcpp/ZrtpPacketGoClear.h>
#include <libzrtpcpp/ZrtpPacketClearAck.h>
#include <libzrtpcpp/ZrtpPacketError.h>
#include <libzrtpcpp/ZrtpPacketErrorAck.h>
#include <libzrtpcpp/ZrtpPacketPing.h>
#include <libzrtpcpp/ZrtpPacketPingAck.h>
#include <libzrtpcpp/ZrtpPacketSASrelay.h>
#include <libzrtpcpp/ZrtpPacketRelayAck.h>
#include <libzrtpcpp/ZrtpCallback.h>
#include <libzrtpcpp/ZIDRecord.h>
#ifndef SHA256_DIGEST_LENGTH
#define SHA256_DIGEST_LENGTH 32
#endif
// Prepare to support digest algorithms up to 512 bit (64 bytes)
#define MAX_DIGEST_LENGTH 64
#define IMPL_MAX_DIGEST_LENGTH 64
class __EXPORT ZrtpStateClass;
class ZrtpDH;
/**
* The main ZRTP class.
*
* This is the main class of the RTP/SRTP independent part of the GNU
* ZRTP. It handles the ZRTP HMAC, DH, and other data management. The
* user of this class needs to know only a few methods and needs to
* provide only a few external functions to connect to a Timer
* mechanism and to send data via RTP and SRTP. Refer to the
* ZrtpCallback class to get detailed information regading the
* callback methods required by GNU RTP.
*
* The class ZrtpQueue is the GNU ccRTP specific implementation that
* extends standard ccRTP RTP provide ZRTP support. Refer to the
* documentation of ZrtpQueue to get more information about the usage
* of ZRtp and associated classes.
*
* The main entry into the ZRTP class is the processExtensionHeader()
* method.
*
* This class does not directly handle the protocol states, timers,
* and packet resend. The protocol state engine is responsible for
* these actions.
*
* Example how to use ZRtp:
*<pre>
* zrtpEngine = new ZRtp((uint8_t*)ownZid, (ZrtpCallback*)this, idString);
* zrtpEngine->startZrtpEngine();
*</pre>
* @see ZrtpCallback
*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*/
class __EXPORT ZRtp {
public:
/**
* Constructor intializes all relevant data but does not start the
* engine.
*/
ZRtp(uint8_t* myZid, ZrtpCallback* cb, std::string id,
ZrtpConfigure* config, bool mitmm= false, bool sasSignSupport= false);
/**
* Destructor cleans up.
*/
~ZRtp();
/**
* Kick off the ZRTP protocol engine.
*
* This method calls the ZrtpStateClass#evInitial() state of the state
* engine. After this call we are able to process ZRTP packets
* from our peer and to process them.
*/
void startZrtpEngine();
/**
* Stop ZRTP security.
*
*/
void stopZrtp();
/**
* Process RTP extension header.
*
* This method expects to get a pointer to the extension header of
* a RTP packet. The method checks if this is really a ZRTP
* packet. If this check fails the method returns 0 (false) in
* case this is not a ZRTP packet. We return a 1 if we processed
* the ZRTP extension header and the caller may process RTP data
* after the extension header as usual. The method return -1 the
* call shall dismiss the packet and shall not forward it to
* further RTP processing.
*
* @param extHeader
* A pointer to the first byte of the extension header. Refer to
* RFC3550.
* @param peerSSRC
* The peer's SSRC.
* @return
* Code indicating further packet handling, see description above.
*/
void processZrtpMessage(uint8_t *extHeader, uint32_t peerSSRC);
/**
* Process a timeout event.
*
* We got a timeout from the timeout provider. Forward it to the
* protocol state engine.
*
*/
void processTimeout();
/**
* Check for and handle GoClear ZRTP packet header.
*
* This method checks if this is a GoClear packet. If not, just return
* false. Otherwise handle it according to the specification.
*
* @param extHeader
* A pointer to the first byte of the extension header. Refer to
* RFC3550.
* @return
* False if not a GoClear, true otherwise.
*/
bool handleGoClear(uint8_t *extHeader);
/**
* Set the auxilliary secret.
*
* Use this method to set the auxilliary secret data. Refer to ZRTP
* specification, chapter 4.3 ff
*
* @param data
* Points to the secret data.
* @param length
* Length of the auxilliary secrect in bytes
*/
void setAuxSecret(uint8_t* data, int32_t length);
/**
* Check current state of the ZRTP state engine
*
* @param state
* The state to check.
* @return
* Returns true id ZRTP engine is in the given state, false otherwise.
*/
bool inState(int32_t state);
/**
* Set SAS as verified.
*
* Call this method if the user confirmed (verfied) the SAS. ZRTP
* remembers this together with the retained secrets data.
*/
void SASVerified();
/**
* Reset the SAS verfied flag for the current active user's retained secrets.
*
*/
void resetSASVerified();
/**
* Get the ZRTP Hello Hash data.
*
* Use this method to get the ZRTP Hello Hash data. The method
* returns the data as a string containing the ZRTP protocol version and
* hex-digits.
*
* Refer to ZRTP specification, chapter 8.
*
* @return
* a std:string containing the Hello hash value as hex-digits. The
* hello hash is available immediately after class instantiation.
*/
std::string getHelloHash();
/**
* Get the peer's ZRTP Hello Hash data.
*
* Use this method to get the peer's ZRTP Hello Hash data. The method
* returns the data as a string containing the ZRTP protocol version and
* hex-digits.
*
* The peer's hello hash is available only after ZRTP received a hello. If
* no data is available the function returns an empty string.
*
* Refer to ZRTP specification, chapter 8.
*
* @return
* a std:string containing the Hello version and the hello hash as hex digits.
*/
std::string getPeerHelloHash();
/**
* Get Multi-stream parameters.
*
* Use this method to get the Multi-stream that were computed during
* the ZRTP handshake. An application may use these parameters to
* enable multi-stream processing for an associated SRTP session.
*
* Refer to chapter 4.4.2 in the ZRTP specification for further details
* and restriction how and when to use multi-stream mode.
*
* @return
* a string that contains the multi-stream parameters. The application
* must not modify the contents of this string, it is opaque data. The
* application may hand over this string to a new ZrtpQueue instance
* to enable multi-stream processing for this ZrtpQueue.
* If ZRTP was not started or ZRTP is not yet in secure state the method
* returns an empty string.
*/
std::string getMultiStrParams();
/**
* Set Multi-stream parameters.
*
* Use this method to set the parameters required to enable Multi-stream
* processing of ZRTP. The multi-stream parameters must be set before the
* application starts the ZRTP protocol engine.
*
* Refer to chapter 4.4.2 in the ZRTP specification for further details
* of multi-stream mode.
*
* @param parameters
* A string that contains the multi-stream parameters that this
* new ZrtpQueue instanace shall use. See also
* <code>getMultiStrParams()</code>
*/
void setMultiStrParams(std::string parameters);
/**
* Check if this ZRTP session is a Multi-stream session.
*
* Use this method to check if this ZRTP instance uses multi-stream.
* Refer to chapters 4.2 and 4.4.2 in the ZRTP.
*
* @return
* True if multi-stream is used, false otherwise.
*/
bool isMultiStream();
/**
* Check if the other ZRTP client supports Multi-stream.
*
* Use this method to check if the other ZRTP client supports
* Multi-stream mode.
*
* @return
* True if multi-stream is available, false otherwise.
*/
bool isMultiStreamAvailable();
/**
* Accept a PBX enrollment request.
*
* If a PBX service asks to enroll the PBX trusted MitM key and the user
* accepts this request, for example by pressing an OK button, the client
* application shall call this method and set the parameter
* <code>accepted</code> to true. If the user does not accept the request
* set the parameter to false.
*
* @param accepted
* True if the enrollment request is accepted, false otherwise.
*/
void acceptEnrollment(bool accepted);
/**
* Check the state of the enrollment mode.
*
* If true then we will set the enrollment flag (E) in the confirm
* packets and perform the enrollment actions. A MitM (PBX) enrollment service
* started this ZRTP session. Can be set to true only if mitmMode is also true.
*
* @return status of the enrollmentMode flag.
*/
bool isEnrollmentMode();
/**
* Set the state of the enrollment mode.
*
* If true then we will set the enrollment flag (E) in the confirm
* packets and perform the enrollment actions. A MitM (PBX) enrollment
* service must sets this mode to true.
*
* Can be set to true only if mitmMode is also true.
*
* @param enrollmentMode defines the new state of the enrollmentMode flag
*/
void setEnrollmentMode(bool enrollmentMode);
/**
* Check if a peer's cache entry has a vaild MitM key.
*
* If true then the other peer ha a valid MtiM key, i.e. the peer has performed
* the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
* to check which of the peers is enrolled.
*
* @return True if the other peer has a valid Mitm key (is enrolled).
*/
bool isPeerEnrolled();
/**
* Send the SAS relay packet.
*
* The method creates and sends a SAS relay packet according to the ZRTP
* specifications. Usually only a MitM capable user agent (PBX) uses this
* function.
*
* @param sh the full SAS hash value, 32 bytes
* @param render the SAS rendering algorithm
*/
bool sendSASRelayPacket(uint8_t* sh, std::string render);
/**
* Get the commited SAS rendering algorithm for this ZRTP session.
*
* @return the commited SAS rendering algorithm
*/
std::string getSasType();
/**
* Get the computed SAS hash for this ZRTP session.
*
* A PBX ZRTP back-to-Back function uses this function to get the SAS
* hash of an enrolled client to construct the SAS relay packet for
* the other client.
*
* @return a pointer to the byte array that contains the full
* SAS hash.
*/
uint8_t* getSasHash();
/**
* Set signature data.
*
* This functions stores signature data and transmitts it during ZRTP
* processing to the other party as part of the Confirm packets. Refer to
* chapters 5.7 and 7.2.
*
* The signature data must be set before ZRTP the application calls
* <code>start()</code>.
*
* @param data
* The signature data including the signature type block. The method
* copies this data into the Confirm packet at signature type block.
* @param length
* The length of the signature data in bytes. This length must be
* multiple of 4.
* @return
* True if the method stored the data, false otherwise.
*/
bool setSignatureData(uint8_t* data, int32_t length);
/**
* Get signature data.
*
* This functions returns a pointer to the signature data that was receivied
* during ZRTP processing. Refer to chapters 5.7 and 7.2.
*
* The returned pointer points to volatile data that is valid only during the
* <code>checkSASSignature()</code> callback funtion. The application must copy
* the signature data if it will be used after the callback function returns.
*
* The signature data can be retrieved after ZRTP enters secure state.
* <code>start()</code>.
*
* @return
* Pointer to signature data.
*/
const uint8_t* getSignatureData();
/**
* Get length of signature data in number of bytes.
*
* This functions returns the length of signature data that was receivied
* during ZRTP processing. Refer to chapters 5.7 and 7.2.
*
* @return
* Length in bytes of the received signature data. The method returns
* zero if no signature data is avilable.
*/
int32_t getSignatureLength();
/**
* Emulate a Conf2Ack packet.
*
* This method emulates a Conf2Ack packet. According to ZRTP specification
* the first valid SRTP packet that the Initiator receives must switch
* on secure mode. Refer to chapter 4 in the specificaton
*
*/
void conf2AckSecure();
/**
* Get other party's ZID (ZRTP Identifier) data
*
* This functions returns the other party's ZID that was receivied
* during ZRTP processing.
*
* The ZID data can be retrieved after ZRTP receive the first Hello
* packet from the other party. The application may call this method
* for example during SAS processing in showSAS(...) user callback
* method.
*
* @param data
* Pointer to a data buffer. This buffer must have a size of
* at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
* @return
* Number of bytes copied into the data buffer - must be equivalent
* to 96 bit, usually 12 bytes.
*/
int32_t getPeerZid(uint8_t* data);
private:
friend class ZrtpStateClass;
/**
* The state engine takes care of protocol processing.
*/
ZrtpStateClass* stateEngine;
/**
* This is my ZID that I send to the peer.
*/
uint8_t zid[IDENTIFIER_LEN];
/**
* The peer's ZID
*/
uint8_t peerZid[IDENTIFIER_LEN];
/**
* The callback class provides me with the interface to send
* data and to deal with timer management of the hosting system.
*/
ZrtpCallback* callback;
/**
* My active Diffie-Helman context
*/
ZrtpDH* dhContext;
/**
* The computed DH shared secret
*/
uint8_t* DHss;
/**
* My computed public key
*/
uint8_t pubKeyBytes[400];
/**
* Length off public key
*/
// int32_t pubKeyLen;
/**
* My Role in the game
*/
Role myRole;
/**
* The human readable SAS value
*/
std::string SAS;
/**
* The SAS hash for signaling and alike. Refer to chapters
* 4.5 and 7 how sasHash, sasValue and the SAS string are derived.
*/
uint8_t sasHash[MAX_DIGEST_LENGTH];
/**
* The ids for the retained and other shared secrets
*/
uint8_t rs1IDr[MAX_DIGEST_LENGTH];
uint8_t rs2IDr[MAX_DIGEST_LENGTH];
uint8_t auxSecretIDr[MAX_DIGEST_LENGTH];
uint8_t pbxSecretIDr[MAX_DIGEST_LENGTH];
uint8_t rs1IDi[MAX_DIGEST_LENGTH];
uint8_t rs2IDi[MAX_DIGEST_LENGTH];
uint8_t auxSecretIDi[MAX_DIGEST_LENGTH];
uint8_t pbxSecretIDi[MAX_DIGEST_LENGTH];
/**
* pointers to aux secret storage and length of aux secret
*/
uint8_t* auxSecret;
int32_t auxSecretLength;
/**
* Record if valid rs1 and/or rs1 were found in the
* retaind secret cache.
*/
bool rs1Valid;
bool rs2Valid;
/**
* My hvi
*/
uint8_t hvi[MAX_DIGEST_LENGTH];
/**
* The peer's hvi
*/
uint8_t peerHvi[8*ZRTP_WORD_SIZE];
/**
* Context to compute the SHA256 hash of selected messages.
* Used to compute the s0, refer to chapter 4.4.1.4
*/
void* msgShaContext;
/**
* Commited Hash, Cipher, and public key algorithms
*/
AlgorithmEnum* hash;
AlgorithmEnum* cipher;
AlgorithmEnum* pubKey;
/**
* The selected SAS type.
*/
AlgorithmEnum* sasType;
/**
* The selected SAS type.
*/
AlgorithmEnum* authLength;
/**
* The Hash images as defined in chapter 5.1.1 (H0 is a random value,
* not stored here). Need full SHA 256 lenght to store hash value but
* only the leftmost 128 bits are used in computations and comparisons.
*/
uint8_t H0[IMPL_MAX_DIGEST_LENGTH];
uint8_t H1[IMPL_MAX_DIGEST_LENGTH];
uint8_t H2[IMPL_MAX_DIGEST_LENGTH];
uint8_t H3[IMPL_MAX_DIGEST_LENGTH];
uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH];
uint8_t peerHelloHash[IMPL_MAX_DIGEST_LENGTH];
uint8_t peerHelloVersion[ZRTP_WORD_SIZE + 1]; // +1 for nul byte
// We get the peer's H? from the message where length is defined as 8 words
uint8_t peerH0[8*ZRTP_WORD_SIZE];
uint8_t peerH1[8*ZRTP_WORD_SIZE];
uint8_t peerH2[8*ZRTP_WORD_SIZE];
uint8_t peerH3[8*ZRTP_WORD_SIZE];
/**
* The SHA256 hash over selected messages
*/
uint8_t messageHash[MAX_DIGEST_LENGTH];
/**
* The s0
*/
uint8_t s0[MAX_DIGEST_LENGTH];
/**
* The new Retained Secret
*/
uint8_t newRs1[MAX_DIGEST_LENGTH];
/**
* The GoClear HMAC keys and confirm HMAC key
*/
uint8_t hmacKeyI[MAX_DIGEST_LENGTH];
uint8_t hmacKeyR[MAX_DIGEST_LENGTH];
/**
* The Initiator's srtp key and salt
*/
uint8_t srtpKeyI[MAX_DIGEST_LENGTH];
uint8_t srtpSaltI[MAX_DIGEST_LENGTH];
/**
* The Responder's srtp key and salt
*/
uint8_t srtpKeyR[MAX_DIGEST_LENGTH];
uint8_t srtpSaltR[MAX_DIGEST_LENGTH];
/**
* The keys used to encrypt/decrypt the confirm message
*/
uint8_t zrtpKeyI[MAX_DIGEST_LENGTH];
uint8_t zrtpKeyR[MAX_DIGEST_LENGTH];
/**
* Pointers to negotiated hash and HMAC functions
*/
void (*hashFunction)(unsigned char *data,
unsigned int data_length,
unsigned char *digest);
void (*hashListFunction)(unsigned char *data[],
unsigned int data_length[],
unsigned char *digest);
void (*hmacFunction)(uint8_t* key, uint32_t key_length,
uint8_t* data, int32_t data_length,
uint8_t* mac, uint32_t* mac_length);
void (*hmacListFunction)( uint8_t* key, uint32_t key_length,
uint8_t* data[], uint32_t data_length[],
uint8_t* mac, uint32_t* mac_length );
void* (*createHashCtx)();
void (*closeHashCtx)(void* ctx, unsigned char* digest);
void (*hashCtxFunction)(void* ctx, unsigned char* data,
unsigned int dataLength);
void (*hashCtxListFunction)(void* ctx, unsigned char* dataChunks[],
unsigned int dataChunkLength[]);
int32_t hashLength;
// Funtion pointers to implicit hash and hmac functions
void (*hashFunctionImpl)(unsigned char *data,
unsigned int data_length,
unsigned char *digest);
void (*hashListFunctionImpl)(unsigned char *data[],
unsigned int data_length[],
unsigned char *digest);
void (*hmacFunctionImpl)(uint8_t* key, uint32_t key_length,
uint8_t* data, int32_t data_length,
uint8_t* mac, uint32_t* mac_length);
void (*hmacListFunctionImpl)( uint8_t* key, uint32_t key_length,
uint8_t* data[], uint32_t data_length[],
uint8_t* mac, uint32_t* mac_length );
int32_t hashLengthImpl;
/**
* The ZRTP Session Key
* Refer to chapter 5.4.1.4
*/
uint8_t zrtpSession[MAX_DIGEST_LENGTH];
/**
* True if this ZRTP instance uses multi-stream mode.
*/
bool multiStream;
/**
* True if the other ZRTP client supports multi-stream mode.
*/
bool multiStreamAvailable;
/**
* Enable MitM (PBX) enrollment
*
* If set to true then ZRTP honors the PBX enrollment flag in
* Commit packets and calls the appropriate user callback
* methods. If the parameter is set to false ZRTP ignores the PBX
* enrollment flags.
*/
bool enableMitmEnrollment;
/**
* True if a valid trusted MitM key of the other peer is available, i.e. enrolled.
*/
bool peerIsEnrolled;
/**
* Set to true if the Hello packet contained the M-flag (MitM flag).
* We use this later to check some stuff for SAS Relay processing
*/
bool mitmSeen;
/**
* Temporarily store computed pbxSecret, if user accepts enrollment then
* it will copied to our ZID record of the PBX (MitM)
*/
uint8_t* pbxSecretTmp;
uint8_t pbxSecretTmpBuffer[MAX_DIGEST_LENGTH];
/**
* If true then we will set the enrollment flag (E) in the confirm
* packets. Set to true if the PBX enrollment service started this ZRTP
* session. Can be set to true only if mitmMode is also true.
*/
bool enrollmentMode;
/**
* Configuration data which algorithms to use.
*/
ZrtpConfigure configureAlgos;
/**
* Pre-initialized packets.
*/
ZrtpPacketHello zrtpHello;
ZrtpPacketHelloAck zrtpHelloAck;
ZrtpPacketConf2Ack zrtpConf2Ack;
ZrtpPacketClearAck zrtpClearAck;
ZrtpPacketGoClear zrtpGoClear;
ZrtpPacketError zrtpError;
ZrtpPacketErrorAck zrtpErrorAck;
ZrtpPacketDHPart zrtpDH1;
ZrtpPacketDHPart zrtpDH2;
ZrtpPacketCommit zrtpCommit;
ZrtpPacketConfirm zrtpConfirm1;
ZrtpPacketConfirm zrtpConfirm2;
ZrtpPacketPingAck zrtpPingAck;
ZrtpPacketSASrelay zrtpSasRelay;
ZrtpPacketRelayAck zrtpRelayAck;
/**
* Random IV data to encrypt the confirm data, 128 bit for AES
*/
uint8_t randomIV[16];
uint8_t tempMsgBuffer[1024];
int32_t lengthOfMsgData;
/**
* Variables to store signature data. Includes the signature type block
*/
const uint8_t* signatureData; // will be set when needed
int32_t signatureLength; // overall length in bytes
/**
* Is true if the other peer signaled SAS signature support in its Hello packet.
*/
bool signSasSeen;
uint32_t peerSSRC; // peer's SSRC, required to setup PingAck packet
/**
* Enable or disable paranoid mode.
*
* The Paranoid mode controls the behaviour and handling of the SAS verify flag. If
* Panaoid mode is set to flase then ZRtp applies the normal handling. If Paranoid
* mode is set to true then the handling is:
*
* <ul>
* <li> Force the SAS verify flag to be false at srtpSecretsOn() callback. This gives
* the user interface (UI) the indication to handle the SAS as <b>not verified</b>.
* See implementation note below.</li>
* <li> Don't set the SAS verify flag in the <code>Confirm</code> packets, thus the other
* also must report the SAS as <b>not verified</b>.</li>
* <li> ignore the <code>SASVerified()</code> function, thus do not set the SAS to verified
* in the ZRTP cache. </li>
* <li> Disable the <b>Trusted PBX MitM</b> feature. Just send the <code>SASRelay</code> packet
* but do not process the relayed data. This protects the user from a malicious
* "trusted PBX".</li>
* </ul>
* ZRtp performs alls other steps during the ZRTP negotiations as usual, in particular it
* computes, compares, uses, and stores the retained secrets. This avoids unnecessary warning
* messages. The user may enable or disable the Paranoid mode on a call-by-call basis without
* breaking the key continuity data.
*
* <b>Implementation note:</b></br>
* An application shall always display the SAS code if the SAS verify flag is <code>false</code>.
* The application shall also use mechanisms to remind the user to compare the SAS code, for
* example useing larger fonts, different colours and other display features.
*/
bool paranoidMode;
/**
* Find the best Hash algorithm that is offered in Hello.
*
* Find the best, that is the strongest, Hash algorithm that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @return
* The Enum that identifies the best offered Hash algortihm. Return
* <code>NumSupportedHashes</code> to signal that no matching Hash algorithm
* was found at all.
*/
AlgorithmEnum* findBestHash(ZrtpPacketHello *hello);
/**
* Find the best symmetric cipher algorithm that is offered in Hello.
*
* Find the best, that is the strongest, cipher algorithm that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @param pk
* The id of the selected public key algorithm
* @return
* The Enum that identifies the best offered Cipher algortihm. Return
* <code>NumSupportedSymCiphers</code> to signal that no matching Cipher algorithm
* was found at all.
*/
AlgorithmEnum* findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk);
/**
* Find the best Public Key algorithm that is offered in Hello.
*
* Find the best, that is the strongest, public key algorithm that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @return
* The Enum that identifies the best offered Public Key algortihm. Return
* <code>NumSupportedPubKeys</code> to signal that no matching Public Key algorithm
* was found at all.
*/
AlgorithmEnum* findBestPubkey(ZrtpPacketHello *hello);
/**
* Find the best SAS algorithm that is offered in Hello.
*
* Find the best, that is the strongest, SAS algorithm that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @return
* The Enum that identifies the best offered SAS algortihm. Return
* <code>NumSupportedSASTypes</code> to signal that no matching SAS algorithm
* was found at all.
*/
AlgorithmEnum* findBestSASType(ZrtpPacketHello* hello);
/**
* Find the best authentication length that is offered in Hello.
*
* Find the best, that is the strongest, authentication length that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @return
* The Enum that identifies the best offered authentication length. Return
* <code>NumSupportedAuthLenghts</code> to signal that no matching length
* was found at all.
*/
AlgorithmEnum* findBestAuthLen(ZrtpPacketHello* hello);
/**
* Check if MultiStream mode is offered in Hello.
*
* Find the best, that is the strongest, authentication length that our peer
* offers in its Hello packet.
*
* @param hello
* The Hello packet.
* @return
* True if multi stream mode is available, false otherwise.
*/
bool checkMultiStream(ZrtpPacketHello* hello);
/**
* Save the computed MitM secret to the ZID record of the peer
*/
void writeEnrollmentPBX();
/**
* Compute my hvi value according to ZRTP specification.
*/
void computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello);
void computeSharedSecretSet(ZIDRecord& zidRec);
void computeSRTPKeys();
void KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output);
void generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
void generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
void generateKeysMultiStream();
void computePBXSecret();
void setNegotiatedHash(AlgorithmEnum* hash);
/*
* The following methods are helper functions for ZrtpStateClass.
* ZrtpStateClass calls them to prepare packets, send data, report
* problems, etc.
*/
/**
* Send a ZRTP packet.
*
* The state engines calls this method to send a packet via the RTP
* stack.
*
* @param packet
* Points to the ZRTP packet.
* @return
* zero if sending failed, one if packet was send
*/
int32_t sendPacketZRTP(ZrtpPacketBase *packet);
/**
* Activate a Timer using the host callback.
*
* @param tm
* The time in milliseconds.
* @return
* zero if activation failed, one if timer was activated
*/
int32_t activateTimer(int32_t tm);
/**
* Cancel the active Timer using the host callback.
*
* @return
* zero if activation failed, one if timer was activated
*/
int32_t cancelTimer();
/**
* Prepare a Hello packet.
*
* Just take the preinitialized Hello packet and return it. No
* further processing required.
*
* @return
* A pointer to the initialized Hello packet.
*/
ZrtpPacketHello* prepareHello();
/**
* Prepare a HelloAck packet.
*
* Just take the preinitialized HelloAck packet and return it. No
* further processing required.
*
* @return
* A pointer to the initialized HelloAck packet.
*/
ZrtpPacketHelloAck* prepareHelloAck();
/**
* Prepare a Commit packet.
*
* We have received a Hello packet from our peer. Check the offers
* it makes to us and select the most appropriate. Using the
* selected values prepare a Commit packet and return it to protocol
* state engine.
*
* @param hello
* Points to the received Hello packet
* @param errMsg
* Points to an integer that can hold a ZRTP error code.
* @return
* A pointer to the prepared Commit packet
*/
ZrtpPacketCommit* prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg);
/**
* Prepare a Commit packet for Multi Stream mode.
*
* Using the selected values prepare a Commit packet and return it to protocol
* state engine.
*
* @param hello
* Points to the received Hello packet
* @return
* A pointer to the prepared Commit packet for multi stream mode
*/
ZrtpPacketCommit* prepareCommitMultiStream(ZrtpPacketHello *hello);
/**
* Prepare the DHPart1 packet.
*
* This method prepares a DHPart1 packet. The input to the method is always
* a Commit packet received from the peer. Also we a in the role of the
* Responder.
*
* When we receive a Commit packet we get the selected ciphers, hashes, etc
* and cross-check if this is ok. Then we need to initialize a set of DH
* keys according to the selected cipher. Using this data we prepare our DHPart1
* packet.
*/
ZrtpPacketDHPart* prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMsg);
/**
* Prepare the DHPart2 packet.
*
* This method prepares a DHPart2 packet. The input to the method is always
* a DHPart1 packet received from the peer. Our peer sends the DH1Part as
* response to our Commit packet. Thus we are in the role of the
* Initiator.
*
*/
ZrtpPacketDHPart* prepareDHPart2(ZrtpPacketDHPart* dhPart1, uint32_t* errMsg);
/**
* Prepare the Confirm1 packet.
*
* This method prepare the Confirm1 packet. The input to this method is the
* DHPart2 packect received from our peer. The peer sends the DHPart2 packet
* as response of our DHPart1. Here we are in the role of the Responder
*
*/
ZrtpPacketConfirm* prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* errMsg);
/**
* Prepare the Confirm1 packet in multi stream mode.
*
* This method prepares the Confirm1 packet. The state engine call this method
* if multi stream mode is selected and a Commit packet was received. The input to
* this method is the Commit.
* Here we are in the role of the Responder
*
*/
ZrtpPacketConfirm* prepareConfirm1MultiStream(ZrtpPacketCommit* commit, uint32_t* errMsg);
/**
* Prepare the Confirm2 packet.
*
* This method prepare the Confirm2 packet. The input to this method is the
* Confirm1 packet received from our peer. The peer sends the Confirm1 packet
* as response of our DHPart2. Here we are in the role of the Initiator
*/
ZrtpPacketConfirm* prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
/**
* Prepare the Confirm2 packet in multi stream mode.
*
* This method prepares the Confirm2 packet. The state engine call this method if
* multi stream mode is active and in state CommitSent. The input to this method is
* the Confirm1 packet received from our peer. The peer sends the Confirm1 packet
* as response of our Commit packet in multi stream mode.
* Here we are in the role of the Initiator
*/
ZrtpPacketConfirm* prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
/**
* Prepare the Conf2Ack packet.
*
* This method prepare the Conf2Ack packet. The input to this method is the
* Confirm2 packet received from our peer. The peer sends the Confirm2 packet
* as response of our Confirm1. Here we are in the role of the Initiator
*/
ZrtpPacketConf2Ack* prepareConf2Ack(ZrtpPacketConfirm* confirm2, uint32_t* errMsg);
/**
* Prepare the ErrorAck packet.
*
* This method prepares the ErrorAck packet. The input to this method is the
* Error packet received from the peer.
*/
ZrtpPacketErrorAck* prepareErrorAck(ZrtpPacketError* epkt);
/**
* Prepare the Error packet.
*
* This method prepares the Error packet. The input to this method is the
* error code to be included into the message.
*/
ZrtpPacketError* prepareError(uint32_t errMsg);
/**
* Prepare a ClearAck packet.
*
* This method checks if the GoClear message is valid. If yes then switch
* off SRTP processing, stop sending of RTP packets (pause transmit) and
* inform the user about the fact. Only if user confirms the GoClear message
* normal RTP processing is resumed.
*
* @return
* NULL if GoClear could not be authenticated, a ClearAck packet
* otherwise.
*/
ZrtpPacketClearAck* prepareClearAck(ZrtpPacketGoClear* gpkt);
/**
* Prepare the ErrorAck packet.
*
* This method prepares the ErrorAck packet. The input to this method is the
* Error packet received from the peer.
*/
ZrtpPacketPingAck* preparePingAck(ZrtpPacketPing* ppkt);
/**
* Prepare the RelayAck packet.
*
* This method prepares the RelayAck packet. The input to this method is the
* SASrelay packet received from the peer.
*/
ZrtpPacketRelayAck* prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* errMsg);
/**
* Prepare a GoClearAck packet w/o HMAC
*
* Prepare a GoCLear packet without a HMAC but with a short error message.
* This type of GoClear is used if something went wrong during the ZRTP
* negotiation phase.
*
* @return
* A goClear packet without HMAC
*/
ZrtpPacketGoClear* prepareGoClear(uint32_t errMsg = 0);
/**
* Compare the hvi values.
*
* Compare a received Commit packet with our Commit packet and returns
* which Commit packt is "more important". See chapter 5.2 to get further
* information how to compare Commit packets.
*
* @param commit
* Pointer to the peer's commit packet we just received.
* @return
* <0 if our Commit packet is "less important"
* >0 if our Commit is "more important"
* 0 shouldn't happen because we compare crypto hashes
*/
int32_t compareCommit(ZrtpPacketCommit *commit);
/**
* Verify the H2 hash image.
*
* Verifies the H2 hash contained in a received commit message.
* This functions just verifies H2 but does not store it.
*
* @param commit
* Pointer to the peer's commit packet we just received.
* @return
* true if H2 is ok and verified
* false if H2 could not be verified
*/
bool verifyH2(ZrtpPacketCommit *commit);
/**
* Send information messages to the hosting environment.
*
* The ZRTP implementation uses this method to send information messages
* to the host. Along with the message ZRTP provides a severity indicator
* that defines: Info, Warning, Error, Alert. Refer to the MessageSeverity
* enum in the ZrtpCallback class.
*
* @param severity
* This defines the message's severity
* @param subCode
* The subcode identifying the reason.
* @see ZrtpCodes#MessageSeverity
*/
void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
/**
* ZRTP state engine calls this if the negotiation failed.
*
* ZRTP calls this method in case ZRTP negotiation failed. The parameters
* show the severity as well as some explanatory text.
*
* @param severity
* This defines the message's severity
* @param subCode
* The subcode identifying the reason.
* @see ZrtpCodes#MessageSeverity
*/
void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
/**
* ZRTP state engine calls this method if the other side does not support ZRTP.
*
* If the other side does not answer the ZRTP <em>Hello</em> packets then
* ZRTP calls this method,
*
*/
void zrtpNotSuppOther();
/**
* Signal SRTP secrets are ready.
*
* This method calls a callback method to inform the host that the SRTP
* secrets are ready.
*
* @param part
* Defines for which part (sender or receiver) to switch on security
* @return
* Returns false if something went wrong during initialization of SRTP
* context. Propagate error back to state engine.
*/
bool srtpSecretsReady(EnableSecurity part);
/**
* Switch off SRTP secrets.
*
* This method calls a callback method to inform the host that the SRTP
* secrets shall be cleared.
*
* @param part
* Defines for which part (sender or receiver) to clear
*/
void srtpSecretsOff(EnableSecurity part);
/**
* ZRTP state engine calls these methods to enter or leave its
* synchronization mutex.
*/
void synchEnter();
void synchLeave();
/**
* Helper function to store ZRTP message data in a temporary buffer
*
* This functions first clears the temporary buffer, then stores
* the packet's data to it. We use this to check the packet's HMAC
* after we received the HMAC key in to following packet.
*
* @param data
* Pointer to the packet's ZRTP message
*/
void storeMsgTemp(ZrtpPacketBase* pkt);
/**
* Helper function to check a ZRTP message HMAC
*
* This function gets a HMAC key and uses it to compute a HMAC
* with this key and the stored data of a previous received ZRTP
* message. It compares the computed HMAC and the HMAC stored in
* the received message and returns the result.
*
* @param key
* Pointer to the HMAC key.
* @return
* Returns true if the computed HMAC and the stored HMAC match,
* false otherwise.
*/
bool checkMsgHmac(uint8_t* key);
/**
* Set the client ID for ZRTP Hello message.
*
* The user of ZRTP must set its id to identify itself in the
* ZRTP HELLO message. The maximum length is 16 characters. Shorter
* id string are allowed, they will be filled with blanks. A longer id
* is truncated to 16 characters.
*
* The identifier is set in the Hello packet of ZRTP. Thus only after
* setting the identifier ZRTP can compute the HMAC and the final
* helloHash.
*
* @param id
* The client's id
*/
void setClientId(std::string id);
};
/**
* @}
*/
#endif // ZRTP