GNU ZRTP4J How To

From GNU Telephony

Jump to: navigation, search

Contents

This how-to gives a short introduction to GNU ZRTP4J. The first part of this how-to describes the overall structure of GNU ZRTP4J: the two main parts GNU ZRTP core and the GNU ZRTP Java JMF/FMJ extension and how they are work together with applications. The second part of the how-to shows some short programming examples.

GNU ZRTP4J Overview

The complete GNU ZRTP4J implementation consists of two main parts, the GNU ZRTP core and RTP/SRTP implementation specific glue code:

  • The GNU ZRTP core is independent of a specific RTP/SRTP stack and the operating system and consists of the ZRTP protocol state engine, the ZRTP protocol messages, and the GNU ZRTP engine. The GNU ZRTP engine provides methods to setup ZRTP message and to analyze received ZRTP messages, to compute the cryptographic data required for SRTP, and to maintain the required hashes and HMAC.
  • The second part of a GNU ZRTP implementation is specific glue code the binds the GNU ZRTP4J core to the RTP/SRTP implementation and provides operating system specific services such as timers, or send data functions. The current GNU ZRTP4J distribution contains glue code to bind GNU ZRTP4J to Java JMF or the open source alternative FMJ.

The JMF/FMJ specific glue code provides the application interface to set up and control the behaviour of GNU ZRTP4J. Applications never access the GNU ZRTP4J core directly.

The JMF/FMJ specific extension ZrtpTransformConnector

ZrtpTransformConnector implements code that is specific to the RTP implementation of JMF/FMJ. ZrtpTransformConnector implements the RTPConnector interface code required by the JMF/FMJ RTPManager and this class provides timeout handling to the GNU ZRTP4J core.

To perform its tasks ZrtpTransformConnector

  • implements the RTPConnector interface and functions to send and receive RTP/SRTP packets. To perfom this ZrtpTransformConnector extends other classes that implement these functions (these classes are not shown in the diagram below).
  • implements the ZrtpCallback interface that provides functions for GNU ZRTP4J core to access RTP/SRTP send/receive functions and to other services like timer, or file I/O.
  • provides ZRTP specific methods that applications may use to control and setup GNU ZRTP4J.
  • can register and use an application specific callback class (refer to ZrtpUserCallback)

How GNU ZRTP4J, JMF/FMJ, and applications work together

GNU ZRTP4J provides a ZrtpUserCallback class that an application may extend and register with ZRTPTransformEngine. GNU ZRTP4J and ZRTPTransformEngine use the ZrtpUserCallback methods to report ZRTP events to the application. The application may display this information to the user or act otherwise.

The following figure depicts the relationships between ZRTPTransformEngine , JMF/FMJ RTPConnector, the GNU ZRTP4J core, and an application that provides an ZrtpUserCallback class.


                  +---------------------------+
         creates  |  ZrtpTransformConnector   |
       +----------+ extends TransformConnector|
       |          | implements RTPConnector   |
       |          +---------------------------+
       |                        |
       |                        | uses
       |                        |
  +----+-----------+      +-----+---------------+      +----------------+
  |  Application   |      |                     |      |                |
  |    creates     | uses | ZRTPTransformEngine | uses |   GNU ZRTP4J   |
  | ZRTP Connector +------+    implements       +------+      core      |
  |  and provides  |      |   ZrtpCallback      |      | implementation |
  |ZrtpUserCallback|      |                     |      |  (ZRtp et al   |
  +----------------+      +---------------------+      |                |
                                                       +----------------+

The picture shows that ZRTPTransformEngine has a janus face: one face to the application and one face to the GNU ZRTP4J core implementation. As an extension to the standard JMF/FMJ RTPConnector ZRTPTransformEngine can provide the RTP/SRTP services to both, the application and the GNU ZRTP4J core. The uses relations are two way uses relations: the application uses the interface of ZrtpQueue to set up and control GNU ZRTP4J and ZRTPTransformEngine uses the ZrtpUserCallback methods to report events to the application (if the application registered an own class that extends ZrtpUserCallback). On the other side ZRTPTransformEngine instantiates the GNU ZRTP4J core class (ZRtp) and uses that interface to control ZRTP, mainly on behalf of the application. ZRTPTransformEngine also registers itself with GNU ZRTP4J core providing the internal ZrtpCallback interface. GNU ZRTP4J uses this internal interface to access various services, such as send data via RTP session or timer support.

Using GNU ZRTP4J

The following paragraphs show some short examples how to use GNU ZRTP4J. Most code snippets are extracted from the small demo programs located in the demo folder.

The GNU ZRTP4J source distribution contains a detailed documentation of the available methods.

How to instantiate a GNU ZRTP4J RTPConnector

The following short code snippets show how an application could instantiate a ZrtpTransformConnector, get the ZRTP4J engine and initialize it. Then the code gets a RTP manager instance and initializes it with the ZRTPTransformConnector. Plase note: in this case the application must set the target address in the connector, not in the RTP manager.

...
   InetAddress ia = null;
   try {
       ia = InetAddress.getByName("localhost");
   } catch (java.net.UnknownHostException ex) {
       System.err.println("Unknown local host: " + ex.getMessage());
   }

   SessionAddress sa = new SessionAddress(ia, 5002);
   SessionAddress target = new SessionAddress(ia, 5004);

   transConnector = (ZrtpTransformConnector)TransformManager
                                                  .createZRTPConnector(sa);
   zrtpEngine = transConnector.getEngine();
   zrtpEngine.setUserCallback(new MyCallback());
   if (!zrtpEngine.initialize("test_t.zid"))
       System.out.println("initialize failed");

   // initialize the RTPManager using the ZRTP connector

   mgr = RTPManager.newInstance();
   mgr.initialize(transConnector);

   mgr.addSessionListener(this);
   mgr.addReceiveStreamListener(this);

   transConnector.addTarget(target);
   zrtpEngine.startZrtp();

...

This example uses different port numbers to set up the RTP receiver and transmitter. To use the ZRTP capabilities the application has to initialize GNU ZRTP4J first. The statement:

     zrtpEngine.initialize("test_t.zid")

performs this initialization.

The string test_t.zid defines the name of a ZRTP Id file (ZID file) that stores the ZRTP identifier, the ZRTP retained secrets and some other data used by ZRTP. The initialize method may take a second parameter of type boolean to enable auto sensing mode (see below). If an application uses the simple form of the initialize method then auto sensing mode is assumed. An application can use setEnableZrtp(boolean onOff) to modify the auto sensing mode explicitly, for example if the application initialized ZRTP with auto sensing mode off.

Note: Currently GNU ZRTP4J requires a ZID file, later versions may run without a ZID file. Running without a ZID file does not compromise security but may be less convenient for an user.

The initialization method opens the ZID file, performs some housekeeping and enables ZRTP processing if no error occurred during the initialization phase. The application may now start the ZRTP discovery phase.

     zrtpEngine.startZrtp();

This method immediately starts the ZRTP discovery phase and GNU ZRTP4J sends Hello packets to its peer. If the peer is already up and has ZRTP enabled both will exchange Hello packets, negotiate the keys, compute the SRTP cryptographic data, and setup the SRTP session. Depending on the application's design and how the application uses GNU ZRTP4J the ZRTP discovery and key exchange may overlap with RTP communication. Therefore the application may send some RTP data packet that are not protected by SRTP.

Start of the ZRTP discovery phase - Immediate and Auto Sensing

GNU ZRTP4J provides two ways to start the ZRTP discovery phase:

  • Immediate mode
  • Auto Sensing mode

The next paragraphs describe these two mode in some more detail.

Immediate mode

If the application disabled auto sensing mode then the application must start ZRTP by calling startZrtp(). GNU ZRTP4J immediately starts to send Hello packets to discover if the peer is available and if it supports ZRTP. If the peer supports ZRTP then both parties continue with ZRTP handshake and negotiate the keys to set up SRTP.

If the peer is either not available or does not support ZRTP then GNU ZRTP4J calls the user callback method zrtpNotSuppOther(). After this callback returns GNU ZRTP4J does not disable ZRTP processing completely but switches into a detect state. See also Restart of the ZRTP discovery phase below.

Auto Sensing mode

If ZRTP was initialized with auto sensing mode the application does not need to call startZrtp(). In auto sensing mode GNU ZRTP4J monitors the traffic on the RTP session to decide when to start the ZRTP discovery phase. GNU ZRTP4J starts the ZRTP discovery phase after at least one RTP packet was sent and received on the associated RTP session.

The auto sensing mode is convenient for applications that open RTP sessions but the actual RTP traffic starts some time later. This is often the case for RTP applications that use a signaling protocol to exchange the actual RTP parameters (port numbers, IP address) with their peer applications. Even after the signaling was successful the applications cannot exactly determine when data starts to flow on the RTP sessions. This starting time depends on a lot of factors, for example network delays or delays in the applications.

Personal tools