Monday, August 18, 2008

Activity Log : GSoC Week #17 (11.VIII - 17.VIII)

This final GSoC week was dedicated for revision (and consequently some modifications) done to the previous work. I'll reproduce the main parts of the already detailed mail sent on the SC dev list in order to summarize the things done. Before that, I must say, that I'll probably continue maintaining this blog, after the end of GSoC too, in case of future ZRTP enhancements, or other news about the integration in SC.

In addition to the revision steps following I must add that for the moment, the GoClear - GoSecure feature presented in the last blog entries is temporarilly disabled mainly due to some standard inconsistencies, that may appear especially in case of transmission errors (for error free calls it is working between SC-SC calls). More about this (and detailed info for how to re-enable it for testing) can be found in one of the mails sent on the SC dev list during last week.

The rest of the revision week activity can be parted in the next sections:
  • I. GUI code restructuring
  • II. Future multistream enhancement issues (and video securing)
  • III. Patches: ZRTP4J as JAR integration and provisionaly no-registrar
  • IV. Tests summarry
  • V. Other revision points

--- I ---

About the code itself, even if it isn't very much added in terms of new classes, and besides the GoClear - GoSecure changes, which meant modifications in many parts of ZRTP4J (temporarily disabled), the rest of the code was pretty convoluted at some points. So, I've done another modification regarding the GUI part, in order to simplify things a bit, and also provide better means of extension for other possible future security solutions. More exactly, I've refactored the ZRTPGUI plugin under the name of SecurityGUI and I've moved all the button related ZRTP actions inside the SCCallback (ZRTP user callback class - in the media.transform.zrtp package). The movement was pretty logical; that class was already handling the changes on the label. Due to this change, the current architecture leaves the former ZRTPGUI plugin (now SecurityGUI) as a simple container for GUI items. These GUI items (now only for ZRTP) can be obtained and used by future various security solutions' GUI handling classes (like SCCallback now for ZRTP). Actually this was the idea from the first place - because of this, being designed also the general security change event, handled in CallSessionImpl, before ZRTP is selected as the default securing algorithm. In conclusion the effect of this GUI code restructuring (which actually isn't pretty much because the only element affected is the secure button) can be resumed for now as:

- as long the secure button is in initial state (command) of "startSecureMode", it has the role of a "general" toggle on/off security button and it's basic send secure change event action is handled in the SecurityGUI plugin;
- in case there is a call session active, setting the security on makes the button being "caught" in the SCCallback class, and after the ZRTP engine initiliazes, to "become" a ZRTP specific security button; this means that the ActionListener for the button is temporarilly set as being the SCCallback and the button will act by switching between ZRTP specific commands until the call is over; then it will go back to the "startSecureMode" command and the status of a general security button

(All this design is in particular very useful, probably among others, for the GoClear part in case will be re-enabled, because the button needs more commands there). I hope, it's clear enough because it's already too much talk about a single (yet complicated...) button :), so I'll get on to the next subject.

--- II ---

I've temporarily disabled also the security for the video RTP manager. This is based mainly on the fact that ZRTP4J doesn't support yet multistream mode, and the way this integration part was implemented until now could cause some unexpected results in case of simultaneous video securing (may probably work, as it is, with some more flags eventually added to the GUI part, but this doesn't comply with the standard which implies using multistream).The disabling is done in CallSessionImpl and can be re-enabled by removing the comments which are pointed out at specific places by "Video securing related code" text.
I actually gave some thought about the multistream extension this week, and some basic opinions about the integration would be:

  • The ZRTPTransformEngine variable used at ZRTPConnector creation in the TransformManager class should be a static variable, instantiated once and passed to all connectors (audio and video - one multistream engine for all streams)
  • The SCCallback (ZRTP user callback class) should follow the same idea as one static variable in the TransformManager class
  • The ZRTPTransformEngine should have an addConnector method instead an setConnector one and manage an array of connectors (one connector per stream)

This is the "binding"/integration part, between ZRTP4J and SC. Further, the connector array management should probably start to relate closely to the standard. I personally intend to continue also after GSoC, when time permits, to further focus on the ZRTP integration enhancement, and I think multistream is the next part I'll consider in more detail.

--- III ---

Another thing I've done this week was to build SC with ZRTP4J included as a JAR. The ZRTP4J JAR was built from the ZRTP4J sources I've worked on, these containing also the (disabled) modifications for GoClear-GoSecure. In order to reduce the JAR's size I've removed the test package, which isn't used anyway in the integration. I didn't commit yet this build version to the encryption branch. For any further development I think it will be more easy for debugging to keep the current branch source structure (with perriodically commits to the main trunk). However, for commiting the GSOC changes into the the main trunk, it might be better to use the JAR version.

A patch which applies to the current encryption branch transforming it into the JAR build version can be found at:

http://students.info.uaic.ro/~eonica/sc/ZRTP4J-jar-integration.patch

The other patch is another update of the provisional no-registrar patch for the current encryption branch, which has the same problems as it did until now, but it also includes a minor fix for the account registration wizard part added to the initial Michael Koch's version. (Related to this patch also, I'll try to add an entry about the problems described a few weeks ago on the issue tracker soon)

This one can be found at:

http://students.info.uaic.ro/~eonica/sc/no-registrar-updated-for-final-gsoc-encryption-branch.patch

--- IV ---

I've tried this weekend to redo some of the tests previously done to have a final GSOC situation. I gathered the ( all successfull :) ) results in a Google spreadsheet at the address:

http://spreadsheets.google.com/pub?key=pISWJIBcSpdFFBkkNNKpvCQ

(it's my first Google spreadsheet so please don't be too critic on how it looks).

I've added also some previous older tests I didn't do anymore, including also the one done by Werner with Minisip/Zfone (hope I got the basic data accurately). Since Free World Dialup seems to switch on fee-based status soon, I've searched for another free SIP provider service. The first one I've found was Free IP Call ( http://www.freeipcall.com/ ... if I remember correctly ) and the secure call test was successfully.

--- V ---

Other things done as a final GSoC revision for ZRTP4J integration:

  • added resource support for all (hope I didn't missed any...) hard-coded strings used for tooltips, label, etc; I've translated these in Romanian also (unfortunately my German is pretty bad :) and the other languages are more or less unknown to me, so somebody else should handle this in case of a mergewith the main trunk);
  • done some more error handling and other fixes;
  • added a few logger entries and some more comments;

Like I also mentioned in the end of the dev list mail, I would like to express my thanks here also to Werner, Romain, Emil and the rest of the SC dev team for guidance, support and for providing an useful learning experience throughout the entire GSoC period.

Monday, August 11, 2008

Activity Log : GSoC Week #16 (4.VIII - 10.VIII)

I'll detail in this blog entry the changes made last week, regarding the GUI part of the ZRTP integration. Part of these are related with the GoClear-GoSecure added feature (about which I got feedback from Werner related to some issues present in the ZRTP protocol - which I actually encountered myself too - and consequently I must say that for the moment even if it's working, it's state is provisional).

One of the main changes done regarding the previous GUI implementation is removing the padlock (secure) button from the SC sources (QuickMenu class) along with the modifications done for access in the SC packages, and moving it in the plugin where the SAS label was already present. The button is moved together with the previous label inside a JPanel which is now the object returned by the getComponent method requested by the implemented PluginComponent interface. This panel, and it's components are obtained in the SCCallback class, which represents the ZRTP GUI callback class, and there are implemented the main modifications on the GUI triggered by various ZRTP actions.

The bundle activator class for the ZRTP GUI plugin implements getter methods for the ResourceManagement service in order to obtain the resources needed for the GUI elements, and also for the Media service in order to trigger the secure change events through the padlock button. You may wonder if this button commands won't actually be more appropriate to be handled more directly from the ZRTP user callback (SCCallback) class, by deriving it from ActionListener, this class after all having the purpose to update the state of the GUI elements. Well, I actually gave a thought before the current approach, and even it may seem a bit convoluted I decided to leave it this way. The main reason is that I thought at the button as a general secure button - not necessarilly a ZRTP related one. This means, that in the future, the current ZRTP GUI plugin, could be extended for other types of securing protocols by maintaining the current GUI elements (which might be common for more than one protocol, at least the button is as main way of toggleing secure mode) and eventually adding other needed elements (and changing the name of the plugin to a more general SecureGUI). The button, consequently maintains the role - as actually specified some time ago when I first designed the GUI part, of toggleing general security on and off for the established call sessions, even if it is placed in the ZRTP GUI plugin. Based on the static security parameter - usingSRTP - a type of securing algorithm is used - now ZRTP is the only available (actually I described all this in the blog entry for week 7, so I won't repeat it here).

Regarding the needs for the provisional addition of GoClear-GoSecure and also the general securing usage of the button, as mentioned in the last paragraph, I decided to establish a basic state model also for the button actions, by associating them specific commands according to the moment it can be pressed.

So, for start the button has associated the "startSecureMode" command - this is the action command specific for the general secure status changing for the CallSessionImpl, having the effect of setting or unsetting the usingSRTP flag; the command associated with the button (and of course the action) remain the same until a call session is started with secure mode on (usingSRTP true) and a securing algorithm usage is initiated

Since the only current secure algorithm solution is represented by ZRTP, further commands for
the button (states) and associated actions (transitions) apply only for ZRTP for now. In case a future securing algorithm will be implemented, specific commands and actions should be added. The current approach practically provides this means of extension (that's why the button starts in a general secure toggle on-off mode, and all may seem a bit complicated).

When a call session starts (or was started - the case of late secure activation), ZRTP is the securing algorithm to be used, and secure mode is set on - the button is toggled - the ZRTPTransformEngine is initialized. This has the effect of calling init from SCCallback (the ZRTP user callback implementation). Init sets the command for the button as "firstZRTPTrigger". You may call this the point where the button "becomes" a ZRTP securing button, by changing it's command (state) from it's previous status of general secure mode toggle button. The action associated with "firstZRTPTrigger" is doing nothing when clicked (actually it should display a forced warning tooltip but for some yet unknown reasons it doesn't seem to work). This is a measure of avoiding crash for the case when only one peer started the call with secure mode on, and the other didn't and will activate it later. So, if the peer will click again the button at this moment attempting to untoggle secure mode this won't be allowed (after all the call is still in unsecure mode). This case is possible only at first ZRTP activation (there's where the command name comes from).

When the other peer toggles secure mode on, or when both peers start the call with secure mode on, after the ZRTP exchange finally takes place with success, when SCCallback calls secureOn, the button command is set (for both peers of course) to "defaultZRTPAction". This command has the same action associated as the general secure mode command "startSecureMode" - changing the secure mode status for CallSessionImpl. This secure mode change event handling will have the effect of generating alternately GoClear and GoSecure requests from the GUI to the state engine when the user toggles the button.

If an user toggles the button off, generating a GoClear request, this will have the effect at the other peer of a SCCallback call to confirmGoClear. In this case the button command (state) is set to "goClearRemoteToggle" and the button is pressed programatically. The action for this case is to switch the secure mode off in the CallSessionImpl the same as usual, but the event sent has (as a new parameter added in the current version) the source set as being remote, not local. This causes the event not to be handled as the user has pressed the button himself, which would normally sent another GoClear request from the GUI to the ZRTP state engine (we don't want that, the other peer initiated the GoClear procedure). Imediatelly after the programatically button press in SCCallback returns the button command state is switched back to "defaultZRTPAction", so a further click on the button will generate a normal GoSecure request.

If an user toggles the button on, generating a GoSecure request, this will be handled in terms of button command (state), and associated action pretty similar with the above case. We got after all the same issue, toggleing the peer button's on programatically but without initiating a GoSecure procedure too at the peer. This button programatically toggleing is done in the showSAS method of SCCallback (probably I should move it to secureOn; I left it there because the SAS is computed only for the first stream in case of more, but if the GoSecure mode will be based on multistream as it should the change is necessary). The programatically toggle on is done with respect to two flags, one indicating that this is not the first call securing (so it is a consequence of a subsequent GoSecure request) and the second telling that the change was generated by peer (this flag is set default as true, and is switched off for itself by the local peer only at a GoClear or GoSecure request and reset back on when the procedure is over).

There is one more command (state) for the button generated by the ZRTP exchange, this being "revertFromAllowClearFailure", and set in the SCCallback when a warning message is received from the state engine, following a GoClear user request which is denied because the peer doesn't support the mode. This causes the button to generate an secure state change event sent to the CallSessionImpl with the source set as revert in order to switch back the previously modified usingSRTP flag, but without further secure change event processing. Also the button is set back as toggled and remains with that command (in this state) set until the end of the call (if the peer doesn't support GoClear at the first attempt of course it won't support it at next attempts either).

Finally, when the call ends the button command (state) is switched back to the general secure mode toggle "startSecureMode".

This is the main detailed description of how the GUI works now - actually mainly the button (the label is change pretty simple). However, like I said, even the implementation works now (if all exchange goes well), according to Werner's feedback, and also with some issues encountered by me also related to the error handling part, GoClear - GoSecure and the related GUI remains after all in a provisional state.

Tuesday, August 5, 2008

Activity Log : GSoC Week #15 (29.VII - 3.VIII)

I've decided last week to go on after all with the GoClear extension even if there were many aspects to be considered about it (like I wrote in the last blog entry). Yesterday, I've finished a basic version of the ZRTP GoClear enhancement. This is a report about the changes done to ZRTP4J and also to the SC sources along with the description of how the GoClear - GoSecure feature is implemented:

Packets added: ZrtpPacketGoClear and ZrtpPacketClearAck simple classes for the GoClear and the ClearAck messages. The first one provides the getter and setter for the clear_hmac field of the packet.

Events added to ZrtpStateClass.EventDataType: ZrtpGoClear to signal GoClear send request to the state engine and ZrtpGoSecure for signaling switching back to secure mode after GoClear.

States added (or with modified handling) to ZrtpStateClass.ZrtpStates: WaitClearAck (was already added to the enumeration but with empty events handling), UnsecuredState (the state in which the engine gets after a successful GoClear transaction), SecureState (added the GoClear related events handling to it); more information about these inside the implementation description which follows

GoClear request:
Let's take a secured call between peer A and peer B as an example. In order to switch to unsecure mode user A clicks the padlock button (displayed as active). This triggers the send of a SecureEvent handled in CallSessionImpl, which finally gets to the ZRTPChangeStatus function's else branch which calls requestGoClear from the ZrtpTransformEngine. The request is forwarded to the ZRTP4J Zrtp class function with the same name. Here a new ZrtpGoClear event is created and sent for processing to the ZrtpStateClass state engine.

The only switch branch for processing the ZrtpGoClear event is the one from the SecureState. In case that the engine finds itself in other state when a ZrtpGoClear event is received this will be handled on the default branch of the state's function switch, meaning it will be treated in a similar way with ZrtpClose. I'm not entirely sure about this part, but it seemed to be somehow logical from the point of view of a user who cancels the call securing by clicking the paddlock button immediately after this is started - the case when the ZrtpGoClear request will reach another state than SecureState. Please note, that the ZrtpGoClear event is, as mentioned, only a request from the user to the state engine and not the event generated by the actual sending of a GoClear packet. However, if the current handling proves not to be appropriate, separate branches can be added for the ZrtpGoClear processing, to all states event handling methods.

GoClear message sending:
This part is contained in the ZrtpGoClear event processing from the SecureState. First, after receiving the ZrtpGoClear request, it is checked if GoClear-GoSecure transition is accepted for the current call. This is based, according to the ZRTP draft section 5.7.2. on the Allow Clear flags sent in the Confirm1 and Confirm2 messages during the first call securing. For this, I've added in the ZrtpPacketConfirm a setter and a getter for the Allow Clear flag. The flag received, in the peer Confirm is obtained in the prepareConfirm2, respectively in the prepareConf2Ack methods (depending on the role). For now the flag sent I've set to be true (in prepareConfirm1 and prepareConfirm2) but this might be probably enhanced with a custom GUI setting option from the user to allow or not allow secure call clearance. Both, the sent and received flag need to be true in order to permit GoClear - this is checked before going forward inside the ZrtpGoClear request processing branch, with a simple AND between the flags, performed by the Zrtp class goClearAccepted new added method. If the check returns true prepareGoClear is called from the Zrtp class. The prepareGoClear method, like the other prepare methods, has the final role to return the GoClear packet, to be sent from the state engine, after computing the clear_hmac. At this point, there might be a possible optimization of preparing the GoClear packet in advance, immediately after having the HMAC keys, or after the call is secured.

After the packet is sent, according to the ZRTP draft, the SRTP stream sending should be stopped. For this part, the afterFirstGoClearSent function from Zrtp class is called from the state engine, which forward calls stopStreaming(true) from ZrtpCallback. I've added this function to the callback interface because there is needed a method at various points in the GoClear-GoSecure interface in order to start and stop the media stream. In case of the ZrtpTransformEngine the implementation of this method sets a holdFlag. This flag is checked in the transform method, and if found to be true null is returned instead of a transformed packet. In this case, the connector's TransformOutputStream class which calls transform, returns the unmodified packet's length (as before) without sending it anymore (practically the packets are dropped). I don't know if this is the best solution for temporarily stopping the SRTP/RTP stream, but this permits to continue sending ZRTP packets "inside" the same stream (which is needed) - the holdFlag check to generate the packet dropping in the transform method from the ZrtpTransformEngine, is done only in case the packet is not a ZRTP packet. Anyway, if someone finds other solutions, there might be a good idea to compare them. After stopping the media stream, the T2 timer is started for GoClear resend as the draft says, and the current engine state is switched to WaitClearAck.

GoClear message receiving:
This is signaled to the state engine as a normal ZrtpPacket event which is processed only in the SecureState, based on the first/last char message comparison, as in the case of other packets. So, after peer B receives the packet from peer A, it generates the response packet ClearAck by calling prepareClearAck from the Zrtp class. This method performs several tasks. It checks the clear_hmac, stops the audio streaming as the other peer did and as the ZRTP draft specifies, clears the SRTP secrets by calling clearSecrets(), deletes the srtpTransformers from the ZrtpTransformEngine by calling srtpSecretsOff in order to switch to normal RTP traffic and returns a pre-created ClearAck packet to the state engine. The clearSecrets function removes the SRTP secrets and related ones as the 5.7.2.1 ZRTP draft chapter states. For now the ones included there are: srtpKeyI, srtpSaltI, srtpKeyR, srtpSaltR, pubKeyBytes, rs1IDr, rs2IDr, auxSecretIDr, rs1IDi, rs2IDi, auxSecretIDi, rs1Valid, rs2Valid, hvi, peerHvi, newRs1 and zrtpSession which is recomputed as a hash of the previous one; I'm not 100% sure if I didn't miss something or if I've added something I shouldn't had - I'll have to analyze more carefully the role of some of the enumerated ones because part of them I've placed there only based on the criteria that anyway there would be recomputed at a GoSecure toggle.

The GoClear message receiving is continued by the state engine with sending the returned ClearAck message. After this, the handleGoClear method is called from Zrtp, which forwards the call to ZrtpCallback (ZrtpTransformEngine) which again forwards it to the user callback which displays an announcement that the peer turned off the secure channel. The ZRTP draft says, I quote: "The endpoint then renders to the user an indication that the media session has switched to clear mode, and waits for confirmation from the user." I implemented this by a displaying a popup only with an OK button. However, I'm not entirely sure that "confirmation" above refers to such a simple announcement like this, or also needs providing the denial option to the user, but the draft doesn't specify exactly what should happen if the user says "no" so I've went on for the first version. After the user confirms by closing the message box and the called functions start returning, the audio stream is resumed as normal RTP from the handleGoClear in the Zrtp class. Finally, switching to UnsecuredState in the state engine concludes this part.

ClearAck message receiving:
While the above actions take place at peer B, peer A was left in WaitClearAck state after sending GoClear. This state can receive two events (besides the default Close/Error branch). First of them is the response - ClearAck - sent by peer B. This is processed as a ZrtpPacket event by the state engine and goes on like this: the GoClear timer is cancelled and after this the goClearOk function is called from the parent Zrtp class. This method calls the next functions: srtpSecretsOff which deletes the srtpTransformers, clearSecrets described above which deletes the SRTP related secrets and stopStreaming(false) which resumes the media stream as RTP from being stopped when sending GoClear. Here also should be done some GUI update (related to SAS display) which I still need to do. Finally the state engine switches to UnsecuredState.

GoClear Timer received:
The other possible event in WaitClearAck state is the Timer event triggered by a delay in receiving ClearAck after sending GoClear. In this case the GoClear is resent. If the timer expires, the clearSecrets function is called to delete the SRTP secrets as specified by the ZRTP draft. I'm not very sure in which state I should leave the peer in case this happens or if the call must be ended. At the first sight it would be logic if not ending the call to leave it in UnsecuredState, but not receiving ClearAck means probably that the other peer didn't get our GoClear so it would continue to try decoding our packets and sending coded stream. Regarding this, the state should probably remain SecureState and the srtpTransformers kept (even if the secrets are deleted, ...which doesn't make pretty much sense anyway but I've left it this way for now - at least you should be able to hear the received stream correctly...). Above all, there is also the fact that at this point the sending stream is stopped, and the draft doesn't say if it should be resumed or not. In conclusion, this timer expiration is a point which probably I must partially reconsider regarding the current implementation.

This is pretty much about the GoClear, but I'm not over yet :) . There is also the GoSecure part which I've tried to implement. (The draft states secure off - on switches should be possible alternatively during a call in case this supports GoClear)

GoSecure request:
Both A and B peers are in UnsecuredState after a successful GoClear exchange. Let's say peer A wants to switch back to secure state after a while. In order to do this the user presses the padlock button again (this should be showing secure off at this moment - padlock in gray - but this GUI part still needs a bit more coding). The way from GUI to the state engine is pretty much the same as in the GoClear case, starting with a SecureEvent handled in the CallSessionImpl and going forward as described in that case until passing a ZrtpGoSecure event finally, to be processed in the event handling function of the UnsecuredState. Here a Commit packet is prepared and sent pretty much the same as in case of sending the Commit packet when a HelloAck is received in the AckSent state. The Commit packet is generated based on the peer's Hello which was saved when the call was first secured as peerHello (in Detect and AckDetected states). The state engine goes into CommitSent state after sending the packet and starting the timer.

Commit receiving in UnsecuredState:
The Commit sent above by peer A, is received by peer B which after the GoClear should also be in UnsecuredState. For this reason the event handling function for this state has also a ZrtpPacket event branch for Commit. An own Commit packet is generated here as in the AckDetected state. I'm not 100% sure this is really necessary but the SRTP secrets related info are deleted at this moment and I left it according to Werner's comment in the AckDetected state: "Parse Hello packet and build an own Commit packet even if the Commit is not send to the peer. We need to do this to check the Hello packet and prepare the shared secret stuff. " After this part things go pretty much like for the Commit received in the WaitCommit state preparing a DHPart1 message, sending it, and switching to WaitDHPart2 state.

From this moment the state engine enters the normal transitions as when securing the call for the first time. The functionality described should cover the most of the GoClear-GoSecure additions. There are also other minor aspects not mentioned but I think this is already enough for a blog entry :). There are still some parts of which I'm not entirely sure and also some which probably can be optimized, as it can be seen during the report. Also, there are still some parts which need to be solved related to the GUI state update. Until now the padlock button was used only to send commands towards the CallSessionImpl - in this case, it must also be set according to the state of the call. There are to ways to try controlling it: one is accessing the UIService from the MediaService and the second is moving it in the plugin I've created for the label - probably using a JPanel to hold them both. I'll try the plugin option because it is the one prefferred after all and if I don't manage to get it working now I'll go for the first one for temporarily usage.

I didn't commit yet the source modifications. I'll probably do it tomorrow after I'll add also some more comments to them (and also fix the GUI part if I manage to do it until then).

Tuesday, July 29, 2008

Activity Log : GSoC Week #14 (21.VII - 28.VII)

A short report about the last week activity:

  • I did one more check regarding the first INVITE sent in the no-registrar mode; one sample of INVITE which it won't be processed by the destination account is the next one:

INVITE sip:test02@w2.x2.y2.z2 SIP/2.0
Call-ID: 01b6fd21bafe064c41d96f2185baf5e0@0.0.0.0
CSeq: 1 INVITE
From: "test01" ;tag=2e27c678
To: "test02"
Via: SIP/2.0/UDP w1.x1.y1.z1:5060;branch=z9hG4bK8f1f612144a850ce33909f5ae91998e7
Max-Forwards: 70
User-Agent: SIP Communicator 1.0-alpha3-0.build.by.SVN Windows XP
Contact: "test01"
Content-Type: application/sdp
Content-Length: 158

v=0
o=test01 0 0 IN IP4 w1.x1.y1.z1
s=-
c=IN IP4 w1.x1.y1.z1
t=0 0
m=audio 5000 RTP/AVP 97 3 0 110 5 8 4
m=video 5002 RTP/AVP 34 26 31
a=recvonly

(w1.x1.y1.z1 is the IP of the call initiator - test01 account; w2.x2.y2.z2 is the IP of the destination peer - test02 account)

The INVITE is the one contained in the originalRequest field of the inviteTransaction before sending it in the createOutgoingCall method of the OperationSetBasicTelephonySipImpl class. I don't have any experience with SDP to be able to tell if something is wrong in that part, but regarding the rest of the INVITE request all seems to be fine I guess. I'll eventually take another look in the RFC this week to be sure.

  • Regarding the minor hold issue encountered last week I'll copy paste from a mail I've sent on the main dev list:

The initial tests I've ran were on three versions of SC: the encryption branch, the encryption branch with no-registrar and the main trunk last revision only. I've merged again the encryption branch with the main trunk and redone the test (also without the encryption branch). The problem is the same. However like I said last time it seems it might be related with the registrar, because in no-registrar mode it doesn't appear. The following call function stack caught at the moment where the CALL_ENDED event is received in CallSessionImpl seems to confirm
this:

CallSessionImpl.callStateChanged(CallChangeEvent) line: 2115
CallSipImpl(Call).fireCallChangeEvent(String, Object, Object) line: 232
CallSipImpl.setCallState(CallState) line: 113
CallSipImpl.removeCallParticipant(CallParticipantSipImpl) line: 94
CallSipImpl.participantStateChanged(CallParticipantChangeEvent) line: 197
CallParticipantSipImpl(AbstractCallParticipant).fireCallParticipantChangeEvent(String, Object, Object, String) line: 131
CallParticipantSipImpl(AbstractCallParticipant).fireCallParticipantChangeEvent(String, Object, Object) line: 76
CallParticipantSipImpl.setState(CallParticipantState, String) line: 179
OperationSetBasicTelephonySipImpl.processTimeout(TimeoutEvent) line: 1215
ProtocolProviderServiceSipImpl.processTimeout(TimeoutEvent) line: 1121
EventScanner.deliverEvent(EventWrapper) line: 371
EventScanner.run() line: 492 [local variables unavailable]
Thread.run() line: 619 [local variables unavailable]

The request which causes the TimeoutEvent in the processTimeout function from ProtocolProviderServiceSipImpl is an INVITE which looks like this:

INVITE sip:eontest02@w.x.y.z:5060;transport=udp SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0;branch=z9hG4bK6028fc60c92752a388b13aa6193b1379
CSeq: 1 INVITE
Call-ID: 936d9c68884f95bb0317582128a2b8a5@0.0.0.0
From: "eontest01" ;tag=45db520a
To: "eontest02" ;tag=d3c9c209
User-Agent: SIP Communicator 1.0-alpha3-0.build.by.SVN Windows XP
Max-Forwards: 70
Contact:
Route:
Content-Type: application/sdp
Content-Length: 173

(where w.x.y.z is the registrar's IP)

I hope the debug results to be of some use, but like I said it might be exclusively related with my registrar/call configuration; the problem seems to appear mostly (but not exclusively) only in the case of one of the peers placing the call on hold - the one which resides on the same machine with the registrar (which is also the one where the above INVITE is timed out); when the other one puts the call on hold it seems to work well most of the time.

I also redone the tests last week with SC on Windows-Twinkle on Linux after the previous merge. The results are the same as previous ones, meaning ok, with one exception which is again related to placing the call on hold. This seems to cause the crash of the encrypted audio channel (after resuming, Twinkle doesn't report anymore the channel to be secured and in addition the audio stream is lost being replaced by garbled noise). This happens both cases: if Twinkle client places the call on hold or the SC client does that. Anyway, again this probably is a Twinkle-SC incompatibility regarding the hold feature. To be sure all is fine, I've checked in SC-SC case if the packets are encrypted also after placing the call on hold (by the peer on which I've said it usually works). The check results were that the encryption goes well also after resuming from hold.

So, in what concerns the encryption branch the hold doesn't seem to have any negative impact so far (in SC-SC calls), the problem mentioned last time not being related with the ZRTP integration and possible being caused by the registrar or the entire test configuration.

  • I've rechecked the CallSessionImpl modifications (with the occasion of the new Hold feature introduction) and thought about restraining the securing only for the audio stream for the moment; However, the idea was based (among others) on the wrong impression that the SAS string is computed twice for the audio and also the video stream, which would have caused problems in displaying. After checking the standard again I've found that I quote: "There is only one SAS value computed per call. That is the SAS value for the first media stream established, which computes the ZRTPSess key, using DH mode." so it seems I had a wrong impression; consequently I've left securing enabled also in case of the video RTP manager too.
  • I've redone the merge (like I said before) and did also some minor fixes while solving the conflicts. The no-registrar patch for the last merge - current version of the encryption branch can be found at:
    http://students.info.uaic.ro/~eonica/sc/no-registrar.patch
    (It's just an update of the older version done against the current sources)
  • I've started thinking on the optional GoClear addition on the current implementation and I've read again the part concerning this from the ZRTP draft, and considered some of the necessary modifications. I've actually done already some minor additions in this direction to the ZRTP4J library, which I didn't commited yet. Like Werner said in his last mail there are however many aspects to be considered, from modifying the current state transitions in the library to enhancing the GUI support. I'll place this for the moment as a secondary priority (being optional), working on it in parallel with other issues - so in case I'll get stuck at some point the time spent with it won't be a problem
  • I've considered also using ZRTP4J as a jar; there are some minor modifications I think that are necessary to the original structure of the library like removing the SRTP related sources which are already part of the SC code; the rest should be easy I think, integrating it "externally" (not inside the media jar), the same way I've modified the BouncyCastle jar integration; I'll try doing that this week along with more GoClear additions to ZRTP4J and some test related work


Tuesday, July 22, 2008

Activity Log : GSoC Week #13 (14.VII - 20.VII)

Last week I focused on debugging the no-registrar patch. I won't reproduce the entire mail I've sent on the main dev list last Wednesday, because it's quite long and maybe a bit over-detailed. I'll summarize it in fewer lines and add some further observations.

Let's take this as a use/test case:

We have two SC peers.
Peer A has three accounts created: one registrar mode account R1 and two no-registrar mode accounts: NR1 and NR3.
Peer B has two accounts created: one registrar mode account R2 and one no-registrar mode account NR2.

The registrar server is shut down.
Peer A has NR1 logged in.
Peer B has NR2 logged in.

Peer B (NR2) calls Peer A (NR1) - the INVITE is sent on NR1@w.x.y.z where w.x.y.z is Peer A's IP address.

The problem: The INVITE request is processed by the SIP stack instantiated by the R1 - not NR1 - account's Protocol Service Provider (which is a registrar-mode type). The stack is also the one which continues the call handling, which makes the wrong ProtocolProviderService to process any further requests.

What I can tell for sure after the debugging done last week: The reason why R1's ProtocolProviderService's SIP stack is the one which handles the INVITE request, is the fact that in this specific test case the R1 account is the one that's loaded first (which also means that the corresponding Protocol Provider Service is the first one from the three registered in the bundle context). The account loading order might differ. After deleting and re-creating all the accounts, the first account loaded was NR3 for example and the SIP stack/ProtocolProviderService handling the INVITE for NR1 were the one associated with NR3.

I tried also other configurations; all lead to the same conclusion - the first loaded account's ProtocolProviderService registered is the one which handles the requests when operating in no-registrar mode - it doesn't matter if the first loaded account it's registrar mode or not, if it's logged in or not or if the request is addressed to a totally different target.

I couldn't find why this happens. I managed to trace the code back into the JAIN SIP RI sources, up to inside the SipTransactionStack class but this doesn't help me. The stack is of course the one corresponding to the first loaded account. What I need to know is the point where the code gets there - how the stack/ProtocolProviderService is selected to handle the request. The getProviderForAccount and getRegisteredAccounts inside the ProtocolProviderFactorySipImpl don't seem to have anything to do with this, being called only prior to the call initiation, in the account loading phase, and I didn't find any bug there. Some more details and also about another test case also can be found inside the mail I've sent on the dev mailing list.

After a lot of debugging done and no success, I decided to check out the revision which was the initial subject for the original patch by Michael Koch - revision 3252, to see what makes the difference. I applied the original patch, activated the no registrar Protocol Provider Service instantiation, and unfotunately there isn't any difference - the same problem is present.

This happens however when the registrar is off. When the registrar is on the calls routed trough it, addressed to registrar mode accounts, reach their target ProtocolServiceProvider successfully.

Anyway, even if I couldn't find out what causes the problem, I made some "fixes" to the initial patch submitted:
  • added the OperationSetTypingNotifications to the others in the registrar mode ProtocolProviderService
  • cut out the REGISTERS_USE_ROUTE property from the AbstractProtocolProviderServiceSipImpl (it was a duplicate - also in the registrar mode provider service)
  • restricted the entire keep alive related functionality only to registrar mode ProtocolProviderService instantiations (I'm not very sure about this but at least the using of REGISTER for keep alive in non-registrar mode doesn't seem to make sense; though I'm not entirely sure about OPTIONS request - I'm not very experienced with SIP; anyway, it was a newer functionality added since the initial patch and I've done the modification also to exclude a potential source for the bug .. but it wasn't)
  • added an if branch in the new sayBye method from the OperationsSetBasicTelephonySipImpl for specific cases of registrar or no-registrar mode provider service (again I'm not entirely certain about if that is correct or not)

These, together with other older and more minor modifications can be found in the patch at this address (done this time against the main trunk revision):

http://students.info.uaic.ro/~eonica/sc/current-rev-no-registrar.patch

Note that this patch allows ProtocolProviderService instantiation for registrar and no-registrar mode also. The older patches had the registrar mode option blocked allowing only no-registrar. Even if the mentioned problem was present also at that time, the call because being handled through a no-registrar ProtocolProviderService as it was intended went on fine.

I'm leaving the no-registrar patch for now, because I've already spent a week with the debugging on it and I didn't manage to solve the main bug. I'll post the main things discussed
here on the dev list, maybe someone experienced with SIP and the JAIN stack can give me a hint eventually, and go back until then to my main GSoC project theme.

I've merged the encryption branch with the latest main trunk revision and I solved the conflicts, but I didn't committed it yet. I'll probably do it soon but first I'll report on the main dev list, a minor bug I found. It's about the new Hold functionality.

The bug manifests the next way: When I put a call on hold, after I release it in aproximately 20 seconds the call ends abruptly without any error message. The logger displays the message from the callStateChangedfunction inside the CallSessionImpl class : "Stopping streaming." like a CALL_ENDED event was received. I didn't debug the code further because I tested this also in no-registrar mode and it seems it doesn't happen, so it might be related with the type of registrar used. However I didn't commit the merge to the encryption branch yet, as I said; I wonder if putting the call on Hold doesn't affect somehow the ZRTP integration at some level and I must take a careful look at it (at a first sight the ZRTP exchange shouldn't be affected at least, but the first thought when encountering the bug above was that is related with the RTPConnector usage for handling the media flow in the ZRTP integration branch; anyway it also occurs between two peers built from main trunk when using my registrar so it seems it wasn't that).

For now you can find the merge patch at this address:

http://students.info.uaic.ro/~eonica/sc/last-rev-merge-patch.patch

That's pretty much all for the moment; I'll probably start thinking on the suggested JUnit testing this week.

Tuesday, July 15, 2008

Activity Log : GSoC Week #12 (7.VII - 13.VII)

Here's a quick report for the last week which was used mainly for testing :
  • Made a basic setup for a Linux (openSUSE 11) partition in order to test SC - Twinkle (available only on Linux) intercommunication using ZRTP (the setup took a bit longer than planned due to some partition losing which needed recovery)
  • Applied the Twinkle patches sent by Werner in order to build it with the latest libzrtpcpp version
  • Done SC-Twinkle tests in no-registrar mode: the ZRTP based encryption activated successfully, and even if there were some codec related problems on one audio channel at first, after repeating the tests these dissapeared (G.711a was selected in the successfull case if I recall correctly)
  • Done SC-Twinkle tests in registrar mode: for registrar I've used this time a very basic configuration of OpenSER on Linux; ZRTP based encryption activated successfully and the calls went fine
  • Registered two accounts at Free World Dialup in order to test using an external SIP service provider
  • Done SC-Twinkle tests through FWD: calling Twinkle from SC went fine regarding the ZRTP activation and encryption; however the SC->Twinkle audio channel was "empty" (the selected codec was GSM this time so I'll probably have to retest trying some codec limitations on Twinkle to see what happens); calling SC from Twinkle hanged unfortunately (I didn't investigate yet the problem further)
  • Done few SC-SC tests through FWD (on Windows platform): all went ok - no problems encountered yet in this case to report (should test some more however)
  • All tests done included calling with ZRTP activated from start and also with ZRTP activation during the call (for the SC peer)
  • All problems reported were encountered also in unsecured calls
  • Werner made an extensive test report also for SC - Minisip/Zfone calls; basically the ZRTP activation and encryption seem to pose no problem; however there were some problems as in my tests regarding general SC communication

This is pretty much all for the testing done until now. I plan to repeat some of them (especially the ones which had problems even if these weren't ZRTP related).

Also I've started at the end of the last week, and went on this week with the debugging of the no-registrar patch. I'm still stuck with the problem of permitting both registrar mode and no-registrar accounts. Essentially this manifests by selecting the wrong (registrar mode account) service provider when two of them, of different types, are present. I've done some debugging on this, didn't found a specific reason yet but managed to finally relate the behaviour with the accounts random generated identifiers. This isn't apparently as strange as it seems at the first sight. Based on the identifiers the order of the accounts at loading seems to differ, and this is the only difference I found so far between calls which go on normally and the ones which fail due to wrong service provider selection. I'll probably post soon a more detailed report on the SC main dev list.

Monday, July 7, 2008

Activity Log : GSoC Week #11 (30.VI - 6.VII)

This week was mainly focused on further no-registrar patch work. Because the activity was pretty much detailed during the week through various mails sent on the public SC main dev mailing list, I'll only make a short summary listed chronologically in the next lines:
  • found out (after quite a while...) the simple solution for the problem in the no-registrar patch pointed out in the last entry - just make sure the proxy related fields are blank (or at least not automatically filled with the IP part of the SIP address) at the account registration and it solves it
  • merged the encryption branch with the SC main trunk
  • re-adapted the adapted patch to fit the modifications; you can find it here: http://students.info.uaic.ro/~eonica/sc/no-registrar-updated.patch ( or as a zip archive - http://students.info.uaic.ro/~eonica/sc/no-registrar-updated.zip )
  • tracked deeper a ZRTP exchange hang issue in the DH phase for which I received a quick solution from Werner
  • added support for the no-registrar option inside the SIP account registration wizard in order to eliminate the hardcoded version which causes all accounts to use no-registrar mode; however this brought up some problems inside the older manually adapted patch - one is related with faulty call disconnect in some cases in the no-registrar mode and the other is about the fact that the registrar mode calls in the patched version doesn't seem to work and needs fixing (no analysis done for the last part yet, for more details about the first check the mailing list); anyway, you can find the (highly unstable for now) full patch here: http://students.info.uaic.ro/~eonica/sc/no-registrar-with-accregwiz.patch ( or as a zip archive including only the no-registrar option added to the account through the wizard - which is stable :) here: http://students.info.uaic.ro/~eonica/sc/no-registrar-accregwiz.zip )

That's pretty much about the last week activity in short terms. For this week I'm planning to setup a Linux partition to make further ZRTP tests, and eventually to take a deeper look into the last no-registrar patch version to see if I can fix the problems mentioned.

Monday, June 30, 2008

Activity Log : GSoC Week #10 (23.VI - 29.VI)

I'll be short this time. The main issues solved last week:
  • done the part related with toggleing secure communication on during a call; both parties can do that regardless the fact they started the call unsecured
  • noticed a bug in the ZRTP init phase which occurs some times in the DH exchange and makes it hang (still must investigate why this appears)
  • tried to apply an older patch manually in order to be able to make a call without the presence of a registrar; see below for detailed info

The patch is based on splitting the ProtocolProviderServiceSipImpl functionality resulting in a more general AbstractProtocolProviderServiceSipImpl as a base class for ProtocoProviderServiceSipImpl (registrar mode) and ProtocolProviderServiceSipNoRegistrarImpl (no registrar mode). The selection of the implementation used is based on an option set for the specific AccountID which is used for making the subsequent calls. This option should probably be available in the account wizard somewhere as the original patch author Michael Koch wrote. For now I've added directly the option to the account properties map inside the code in the ProtocolProviderFactorySipImpl loadAccount method to see if the patch works - this means that all the accounts will use the no registrar option, but like I said is only to test the patch. The result is that the two new accounts I created for testing (one on my PC and one on my notebook), start as expected looking like normal registered ones (online and being able to make calls). Anyway, when I try to call one of them from the other, the endpoint that is alerted and starts ringing is the same that makes the call. This happens despite the fact that during a debug session the INVITE message seems to be perfectly fine (I'm not a SIP expert, but that's my impression and to be sure I've checked the standard once more). I've ran the debug step by step (except the JAIN SIP jar contained sources) until the ringing starts (which happens in the createOutgoingCall method inside the OperationSetBasicTelephonySipImpl class at inviteTransaction.sendRequest() - line 295), and all seems to be in order as much as I can tell, like I said, regarding the INVITE request. I'll probably should check again the patch and see if I didn't miss something, or to do a deeper check in the sources to see if it's not related with something modified since the patch was issued.

I didn't modify the sources on svn branch yet with the patch. I've applied it on a different local copy on my PC. I'm posting the no-registrar patched sip package and ProtocolProviderFactory source in the form they now are as a zip archive at this address:

http://students.info.uaic.ro/~eonica/sc/no-registrar.zip

Overriding them on the current date svn encryption branch sources should bring you to the no-registrar patched version status of SC I've reached.

Monday, June 23, 2008

Activity Log : GSoC Week #09 (16.VI - 22.VI)

How things went on for the last half of week since the previous blog entry ( some good news this time :) ) :
  • solved the bouncycastle jar issue with some help from Emil and passed the problem explained last time; the jar used right now is the last version 1.39 and is imported "externally" = isn't included any more inside the media.jar

  • got stuck (for quite a while...) with an InvalidKeyException in ZRTP4J (in the preparation of the Confirm1 message at the initialization of the AES cipher - line 1246); eventually I found out that - quote from the Bouncy Castle site: "Note: with JDK 1.4 and later you will need to have installed the unrestricted policy files to take full advantage of the provider. If you do not install the policy files you are likely to get something like the following: java.lang.SecurityException: Unsupported keysize or algorithm parameters" ; the unrestricted policy files do indeed solve the problem, but this probably means the user should install them (installation means overwriting the original jars in the system's Java path; maybe this might be done through SC setup ...) ; anyway, the idea is that these are needed now for a succesful run and can be found at : https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jce_policy-6-oth-JPR@CDS-CDS_Developer (this is for JDK/JRE 1.6 ; for other versions look for JCE unlimited/unrestricted policy files on the version's download page)
  • removed some more bugs (mainly from CallSessionImpl), updated the GUI with the secure status (see below for details) and finally made a successful SC-SC call secured through ZRTP :)

More details about the GUI additions:

I've added a label to display the SAS and actually the current secure or not status for the call. This is only provisional for now as discussed with Romain in the last GUI related mail. Anyway, I've done it using a GUI plugin. One reason is that eventually it should be done through a plugin so I thought it will be ok to try this from now. Another reason is that other way of sending a message from the media service to the GUI label would have been quite "invasive", needing probably some modifications in the current UIService and adding another ExportedWindow from the main interface. So I went on for the current approach, and based on the AboutWindowPluginComponent related source code inside the Branding plugin (due to the fact the GUI plugin tutorials on the SC dev page seem to be a bit outdated), I created a small JLabel based PluginComponent and added it for now, through a GUI Plugin, near the previous made button.

When not during a call this looks like this:


If the user didn't try to activate secure communication on his client through the nearby button - the call will be unsecured (the ZRTP engine starts with autosensing off):



If the user enabled secure communication for his client but the other peer didn't the call starts the same as above unsecured, but another tooltip is displayed regarding the cause:



And finally if both users have secure communication enabled before the call, the SAS string is displayed:


All these - design, behaviour, etc, like stated before, have provisional status for now. The main idea was to know if it works and how can be done. When it's appropriate, I'll try moving them in another GUI location like discussed.

Like I said, I've managed to run the first SC-SC ZRTP secured call. This is however done with autosensing on for both sides, meaning that the both peers activated secure communication before the call. In case one of them didn't the call goes on unsecured. Actually, the possible cases of how the call goes in case of activating/deactivating the secure status could be very well summarized through the presented screenshots. So, in conclusion, all goes well for now in case any modification in the secure comm status for the client is done between the calls. Toggleing on secure communication during a call doesn't work at this moment and I'll try to focus on it this week (I'll probably should go deeper for this in Werner's sources). Toggleing off secure communication during a call should be similar with the sending of the GoClear optional message, so I'll leave it for later.

I uploaded the current sources to the svn encryption branch. I didn't manage yet to comment all the changes/additions (I'll try to do that this week). That should be all for now.

Wednesday, June 18, 2008

Activity Log : GSoC Week #08 (9.VI - 15.VI)

I'll be shorter this time, summarizing in a few lines the activity for last week's final half and the issues appeared at the beginning of this one:

  • removed quite a few bugs from CallSessionImpl and TransformManager
  • passed the problem with the NoClassDef exception through some refactoring adding Werner's ZRTP4J sources inside the SC tree
  • refactored the refactoring to bring back ZRTP4J in the initial structure and solved the NoClassDef exception the right way by adding the ZRTP4J sources inside the media.jar at build time through build.xml; this approach will permit the future modification to integrating ZRTP4J through a jar very easy - the imports will remain in the same form as now, and the lines in the build.xml will be changed to reflect the jar integration, similar to how the bouncycastle jar is handled at the moment
  • modified the used ZRTP4J sources with Werner's last sources version
  • got stuck into a problem, since this week started, related to how JCE (Java Cryptography Extension) works - detailed below
  • added the current sources on the java.net sip-communicator dedicated branch - https://sip-communicator.dev.java.net/svn/sip-communicator/branches/encryption

Now, a few more words about the problem I'm facing. Probably the best way to start explain it is actually pasting the exception I get:


[java] java.lang.SecurityException: JCE cannot authenticate the provider BC
[java] at javax.crypto.SunJCE_b.a(DashoA13*..)
[java] at javax.crypto.Mac.getInstance(DashoA13*..)
[java] at gnu.java.zrtp.ZRtp.(ZRtp.java:325)
[java] at net.java.sip.communicator.impl.media.transform.zrtp.ZRTPTransformEngine.initialize(ZRTPTransformEngine.java:641)
[java] at net.java.sip.communicator.impl.media.CallSessionImpl.initializeRtpManager(CallSessionImpl.java:1578)
[java] at net.java.sip.communicator.impl.media.CallSessionImpl.allocateMediaPorts(CallSessionImpl.java:1519)
[java] at net.java.sip.communicator.impl.media.CallSessionImpl.createSessionDescription(CallSessionImpl.java:989)
[java] at net.java.sip.communicator.impl.media.CallSessionImpl.createSdpOffer(CallSessionImpl.java:573)
[java] at net.java.sip.communicator.impl.protocol.sip.OperationSetBasicTelephonySipImpl.createOutgoingCall(OperationSetBasicTelephonySipImpl.java:257)
[java] at net.java.sip.communicator.impl.protocol.sip.OperationSetBasicTelephonySipImpl.createCall(OperationSetBasicTelephonySipImpl.java:116)
[java] at net.java.sip.communicator.impl.gui.main.call.CallManager$CreateCallThread.run(CallManager.java:833)
[java] Caused by: java.util.jar.JarException: Cannot parse reference:file:sc-bundles/media.jar
[java] at javax.crypto.SunJCE_c.a(DashoA13*..)
[java] at javax.crypto.SunJCE_b.b(DashoA13*..)
[java] at javax.crypto.SunJCE_b.a(DashoA13*..)
[java] ... 11 more

Ok, the main points of interest, to say so, are the two bolded lines. After some "Google research" done, I've reached a conclusion for the moment (but I'm not very sure about it..). The SecurityException is thrown because the Sun provided implementation of the JCE needs to authenticate any Provider used for cryptography services. According to the bouncycastle site their jar is signed, but... the jar I use at the moment isn't actually the original jar from their site. It is a modified version, made by Su Bing last year, for which I don't know exactly the modifications made. Still, I don't know if the problem resides at the used bouncycastle jar because the exception states it is caused by a jar exception of not being able to parse the media jar. Why is the media jar involved in all these ? Because the contents of the bouncycastle jar were integrated by Su Bing last year at build time through build.xml in the media.jar, which represents the media bundle, in order to be possible to use bouncycastle services. This is related to the OSGi bundle architecture, and was, as far as I can tell after some testing done about a month ago, the reason for the modifications done by Su Bing to the bouncycastle jar = using the original one as it is results in the media bundle failing to start (if I recall corectly). But, as I said before, I'm not sure if the SecurityException thrown is related to these modifications (which again I don't know exactly what about they consist in or how significant they are) or if it is based only on the fact the the bouncycastle code is "embedded" inside the media jar.

Ok, this is the description of the problem. Since Monday I was able to think on some solutions, but I'm not sure any of them will work (or how good they are).

One - quite innapropriate - found after another round of "Google research" can be to use a clean-room JCE implementation which won't try to check at runtime if the bouncycastle provider is authenticated. Like I said I find this quite innapropriate regarding the fact that the bouncycastle jar is signed and in theory there shouldn't be a problem related to the authentication. Besides that, I've looked a bit for some clean room JCE implementations and there aren't many of them (though I didn't do exactly an extensive search - BouncyCastle provides one and I found one more provided by Cryptix). Add to this that I don't know if they're compatible with the current sources (the BouncyCastle one is JDK 1.3 compliant and about the Cryptix one I'm not very sure). Anyway, this approach might be a temporarily solution if nothing else works.

The other solutions focus on eliminating the cause of the problem, rather than effect, about which cause I'm not sure what actually is it, as stated above, in the problem description. So, one option, would be to try separate the bouncycastle jar from the media jar and to import it as an external source, which I don't know if it's possible. If I recall correctly there is a Bundle-Classpath parameter available for the OSGi bundle manifest, but at this very moment when I'm writing I'm not sure if it could be of some use for this. I'll do a bit of research to find out, but any feedback from someone experienced with the OSGi architecture for this and actually for a possible solution for the whole matter should be very helpful.

Another solution, which again I don't know it will solve the problem is to try using the original bouncycastle jar. For this I should try using it again, compare the logs and the behavior, and see if I can't figure out what is the problem exactly. If this won't be enough (and according to last time attempt, might not be..) I'll probably should unpack the modified one and look at the differences (there is a small problem here - the modified one is version 1.37 and the bouncycastle provided one reached version 1.39 meanwhile, and I don't see any web archive with older releases on their site, but maybe I didn't look deep enough.. and anyway a comparison should be possible between different versions too).

This is pretty much what I have in mind at this moment as possible solution. Any feedback about any part of the problem - cause or solution is very welcome.

In the next part of this week, I'll try to find a way to solve it and do some more debugging for the current sources in parallel if possible + adding the SAS support as a provisional solution in the main GUI interface until integrating it through a plugin.

Wednesday, June 11, 2008

Activity Log : GSoC Week #07 (2.VI - 8.VI)

First of all, sorry about the delayed posting. Got stuck with a small problem about which I'll detail in the end.

The code modifications since last week can be found here:

These contain also Werner's sources ( that's the reason for their size :) ), about which I'll talk a bit later.

I'll detail now what I've managed to do since last week. I've changed a bit the steps discussed - more exactly, I've started focusing on the GUI part before actual finishing the library integration (where actual finishing = mainly eliminating bugs) because the GUI actions are related to triggering ZRTP startup.

So, I'll start explaining how things work from the point where the user activates the secure communication until the library code is used. I think it will be more clear this way.

I decided to activate the secure communication (and when I tell secure - I mean it in a general way, not directly related to ZRTP) through a button on the main quick menu toolbar. Actually I had an initial idea, which I started to develop to add this button and the additional ZRTP specific features (like a SAS label) through a ZRTP GUI plugin. But it didn't seem right because first of all - like I said - the button isn't actually related only to ZRTP, and above all it has a pretty general/important function by triggering secure communication from the media package. So I've decided to separate it from the ZRTP GUI part (about which I need a feedback on how and more important where it's prefered to be added; I'll detail later). In conclusion, I've added the specific button and it's handler to the QuickMenu class. I've also added the ability to provide the media service on the GUIActivator, the media service being used in the QuickMenu class by the button handler to set a general secure on/off communication parameter. That's about all the modifications I've done inside the GUI part of SC. I hope I wasn't very "invasive" :). You can see how it looks by running SC or in the next screenshot:







(1. I won't mind if you don't agree with my button "design" and somebody repaints it :) and 2. I really don't know why the mouse cursor wasn't caught in the screenshot but I assure you the tooltip appears because it's there :) )

I'l continue now with the way the code "flows" starting from the button and I'll be back to GUI in the end. Like I said, the button sets a general parameter to toggle communication security on and off. This parameter is actually the usingSRTP boolean member of CallSessionImpl for which I've changed a bit the role as it follows.

There are two distinct moments when the user could toggle the secure status on or off.

1. There isn't any call going on

In this case any call that follows the on/off secure setting made by user should use that setting by default to choose what kind of call - secure/unsecured - to start (e.g.: the user starts SC - lets' say usingSRTP is false by default, toggles secure communication on - usingSRTP true, makes a call - the call will be secured). The problem was that usingSRTP was an instance variable so it didn't exist until the call was created and in the above example it should be set before this happens. The solutions were to make it static or to pass it as a parameter at call session creation by moving it in the MediaServiceImpl. I decided for the first solution to keep as much as possible in the call session and to interact less with the media service. Anyway this can be discussed (with respect to section 2. below), because the value setting for usingSRTP at a button click is still done by using a getter and a setter exported by the media service. I didn't see other entry point possible for the Call Session.

2. There is a call going on

This will be the case when the user is involved in a call and decides to change the secure status for the communication (e.g. : GoClear in ZRTP from secure to normal stream or GoSecure from normal stream to secure). The same thing as before happens with the usingSRTP parameter, but this time also an event will be received by the CallSessionImpl instances notifying that a change in the security status is indicated. I've designed a SecureEventListener/SecureEvent mechanism for this. More exactly the CallSessionImpl implements the secure listener and registers itself as it's own listener in the callStateChanged method when CALL_IN_PROGRESS is received - when call starts, and removes itself from the listeners Vector in the same method at CALL_ENDED when the call ends. So, between these two moments the CallSession will handle, in the secureStatusChanged method, any usingSRTP secure/unsecure modification triggered by the user through the GUI.

Now, like I said in the start, usingSRTP is exactly what it sounds like = using SRTP general indication independent of the key management solution, and the behaviour described above respects also this, which keeps open the posibility of future adding other key sharing solutions. For this, a very basic approach (which should be further developed) is the small implementation done in the keyshare package, which was present also in the last patch, but I've modified it a bit by changing the names to keep it more distinct to the cryptography services providers, and also added a priority field. This should be used in a more advanced algorithm in case of more than one key management systems are present, to select which of them should be used. For now ZRTP being the only one considered, it has the highest priority :). The key management type to be used is being held in the selectedKeyProviderAlgorithm. Actually, this is, I might say the point where the implementation gets different, until now being based on general secure on and off. Based on this selectedKeyProviderAlgorithm type (which might be for now ZRTP, Dummy hardcoded SRTP keys or none) the few general actions in CallSessionImpl related with communication securing are performed different. For example the handling of the SecureEvent during a call which announces a change in the secure mode is ignored in case of Dummy hardcoded SRTP or no securing algorithm, and the Go Clear or Go Secure actions are performed only in case of ZRTP. About this, I've used Werner's ZRTPTransformEngine startZrtp and stopZrtp for now to have some handling methods there, but for stopZrtp I know it's not exactly what is needed for GoClear. About startZrtp I'm not sure if it's ok or not for a GoSecure, after a previous GoClear, as I didn't manage to get deeper yet into the code and compare it with the ZRTP standard, but I suppose it's close :). Anyway, I didn't manage to make a succesfully test yet to see how it actually works (I'll tell in the end where I'm stuck now).

Well, I've reached the point where I should talk about how Werner's library is integrated besides the mentions made on GoSecure/GoClear above. It's not very much to tell. Essentially I've followed the steps on Werner's demo package and adapted to the CallSessionImpl class ( it took more figuring how I'll use Werner's modified SRTP packages :) ). So, the integration (as it's now implemented) could be resumed in the next ideas:


  • based on the selectedKeyProviderAlgorithm type in the initializeRtpManager a ZRTP connector is created by calling the specific function from the TransformManager, after which the RTP Manager is initialized with the connector as parameter

  • ZRTP is actually started in the update methods for the ReceiveStream and SendStream events (in case events are new stream events) by getting the engine instance from the connector and calling startZrtp; I've added an isStarted getter to Werner's ZRTPEngine for this in order not to call the startZrtp method in both of the update handlers; I'm new to JMF and to Werner's code also and I'm not sure if all this is actually OK (I still have some bugs before this point and didn't reached it yet) so some feedback after looking into the sources will be welcome

  • The same startZrtp (and for now stopZrtp) is called also as said before, for handling any during-call-security-status-change-events

  • Werner added the option of choosing a custom Java Security Provider for cryptographic services and modified the SRTP packages accordingly, so I've added in the TransformManager class two functions for minimum support of this customization, somehow similar to the way I've dealed with the custom key management system described above; the functions are initializeProviders which should query the current supported security services providers, and selectProvider which should select one of them for usage; of course for now only one option here too - BouncyCastle; any way the mentioned functions should be further developed and also I'm not sure the way I've integrated them now it's the best approach possible; also related to this I've added a cryptoProvider parameter to the createZrtpConnector too

  • The createZrtpConnector function in the TransformManager practically concludes the access to the library instantiating a ZRTPTransformEngine, selecting a cryptography services provider, creating the connector, and making the necessary initializations in the engine (setConnector, setUserCallback, setCryptoProvider)

About the user callback initialization of the ZRTP engine - I've defined a SCCallback class in the keyshare.zrtp package to be used for this, class which resembles pretty much the internal MyCallback class from Werner's demo package. The difference is that I've provided GUI access in it by getting a UIService reference from the BundleContext provided by the MediaActivator. From this reference to UIService we easily can bring up popup messages (as all functions do at the moment in the respective class). The problem is that I don't know how this approach will comply with the requirement stated by Werner that I quote: "All methods of the user callback class and classes that extend this class run in the context of the RTP thread. Thus it is of paramount importance to keep the execution time of the methods as short as possible." I'll need some feedback about this from an SC GUI developer, or we should see at testing how it works. Also, popup messages aren't the proper solution for all the GUI interaction parts in that callback class. The SAS message for example should be displayed for the entire call duration I think (or at least it should be possible to do this, correct me if I'm wrong) so a Label or some other GUI element should be added for this to the interface. The main problem for me at this point is where :). To be more clear for a feedback from a GUI developer the SAS message is an authentication string for the current call which the user should be able to check with his peer by voice (we could force the user to check the SAS when it's established through a popup message but I don't recall this being mentioned by the standard :) so this is the reason why we should keep it on for the entire call duration). The string has 4 digits as I recall, but I think it depends on the rendering algorithm (I need some feedback from Werner on this, or I'll take another look in the standard to see exactly). So, like I said, the main problem was where to display this. An idea was in the toolbar near the GoSecure button only when the call is active and security is on. Anyway I don't recall exactly at this moment if there are other GUI elements beside this and various information and confirmation messages. For the last part, as I've read in the tutorial, the UIService provides Confirm dialog and Input Dialog as easy as the popup messages so it shoudn't be a problem. If there are any other elements (of which I don't recall to be at this moment), I'll ask Werner to give some feedback if possible. About how the SAS part will be implemented there are two options - one to add it as I did with the button, or to make a GUI plugin for this. Again I'll need some feedback from a GUI developer. (I left actually some minimum remains from the initial plugin I've started in the sources to develop it as a plugin for a SAS but it seems a bit innapropriate - it may be not, though - to make a plugin for displaying only a label; if there are some other elements it's another story) . One more idea related to the SAS is that if adding it as a JLabel to the QuickMenu isn't possible (maybe, it's not supported) it could be very well added as another (bigger) inactive button on which we can change the caption string. That will be pretty much about the interface issues I face right now.

I left the bigger problems for last. The first of them was the fact that Werner modified the SRTP implementation and added it as component packages to ZRTP4J. So I didn't know what to do as first - to use them directly from ZRTp4J or to override them on the previous SC code. Finally I chose the last, on the reason because after all SRTP might be used by other key management system also, and seemed more appropriate. For now as it can be seen also from the patch, I've modified the SRTP packages in the SC code to Werner's version and added only:

  • gnu.java.zrtp

  • gnu.java.zrtp.jmf.transform

  • gnu.java.zrtp.packets

  • gnu.java.zrtp.utils

  • gnu.java.zrtp.zidfile

  • demo


I didn't add the rest because there would be duplicates in the ZRTP4J and SC code. I've also modified the references in the ones mentioned to point to the ones in SC. Like I've said these arent the original SC SRTP packages, I've modified them according to Werner's optimized sources. I also was able to take a look at the modifications Werner did while doing this and I might have some questions (but in another post, after I'll look again at what I didn't understand at the first time). I made a small modification also, by changing a ZrtpUtil package function array comparison call to an inline implementation in order to keep SRTP not depending on the rest of ZRTP library. I know that eventually ZRTP probably should be used as a jar, but for now during the development phase it seems better to integrate it as direct sources (still I don't know if the described approach is the best and I'd like some feedback from Werner and Romain also).



Also about this way of integrating the sources for now, and if this is ok or not, might be related the point where I'm stuck now. To be more clear the packages are added as they were sent by Werner in the mail I've got, moved in the src folder of SC. So the imports are made using import gnu.java.zrtp... The build goes well, but at exec time I got a
java.lang.NoClassDefFoundError: gnu/java/zrtp/jmf/transform/zrtp/ZrtpTransformConnector in CallSessionImpl at the TransformManager.createZRTPConnector call (line 1558) . I'm not stuck at this since very long (so I hope I'll probably figure it out eventually) but until now I don't see a reason for it. The class is built and it is there at the respective path in the bin folder of SC. Maybe I should add some imports in a manifest file, but the Felix console doesn't report any problem related with the gnu packages at runtime so I don't know if the problem resides here. Anyway I'm not very experienced with OSGi to know for sure. Also, I don't think this is a classpath problem, the gnu folder being at the same level with the net folder in src, and the imports are made in similar way. If somebody could provide some help until I'll figure it out, I'll appreciate it very much.



This should be all for the last week (and the beginning of this one also). I'll be waiting for some feedback, until which I'm gonna try getting over the mentioned problem and further testing the current implementation form. Also, I'll try getting the sources posted on the SC dedicated svn branch at java.net until next week.

Tuesday, June 3, 2008

Activity Log : GSoC Week #06 (26.V - 1.VI)

Finally got over with my exams last week, so I started writing my first lines of code in the weekend. You can find these here:



I've also received Werner's code (which I might say again is much more advanced than I am into the matter). After I've looked into it, though I didn't finish yet, my opinion is that it will possibly be a solution not very hard to do, to follow his integration approach, which differs a bit from mine, and find a way to bind it to SIP Communicator; or may also be a solution to combine the approaches, like I'll describe in the end.

Until then, a few words about what I have done until receiving Werner's code:



The sources posted consist mostly of a simple skeleton solution for binding the ZRTP services into the current SRTP implementation. I've tried to make detailed comments inside them so I'll be more short here describing only the general idea:



(I'm not sure how clear I'll be, so I'll recommend for everybody who reads forward to look at the same time on the sources also to get the idea)



I have added two packages : keyshare and keyshare.zrtp.



The connection "starts" in this case also, as for SRTP, in the CallSessionImpl class, in the initializeRTPManager method. The keyshare package contains a very small interface KeyProvider which is intended to define the current supported key management/provider types (for now only ZRTP and a DummyProvider) and has a method for retrieving the provider type. The interface is implemented by two classes, ZRTPProvider and DummyProvider as mentioned, which act more like some constants. The createSRTPConnector in the TransportManager class takes as last parameter an object which implements KeyProvider. Based on the provider type retrieved through the method I've mentioned above it acts accordingly to start the associated implementation for key management (takes a branch on an if to be more clear :) ). In case of ZRTP provider type it instantiates a ZRTPConnector (about which I'll talk below). In case of a DummyProvider procedes as it did before instantiating a SRTPConnector with the hardcoded keys. I made all this selection process (which actually should be developed a bit more) with the purpose to offer a possible entry point for other key management solutions.



(Actually, the KeyProvider interface defined also methods for getting and setting the crypto parameters needed to provide for the SRTP transformation, but I removed them yesterday because I found it to be a bit redundant - the SRTPTransformEngine has already the getters for these; so in conclusion the Provider type classe might look a bit strange and probably could be reduced only to the constants - or could be let this way in case of possible additional methods to be added)



This was the description of the "choosing" of the ZRTP key management solution or any other one (which process isn't final, as I said). Now, focusing on the actual ZRTP part. I've left the description at instantiating the ZRTPConnector in the TransformManager. The ZRTP related classes are contained in the keyshare.zrtp package, and of course the ZRTPConnector is also there. Before going forward, I'll insert a scheme which presents the most important points of interconnection in this package, regarding the integration problem.





I know it's not really UML but I hope it's understandable :). I've described also inside the source comments how it works, so I won't get into deep details here. Shortly speaking, it's like I said a skeleton implementation which runs in the next way:

  • ZRTPConnector extends TransformConnector and overrides all the methods concerned with the input and output stream creation
  • ZRTPConnector makes use of two specific ZRTP input and output stream classes, which extend TransformInputStream and TransformOutputStream, overriding the read and write methods.
  • These methodes are the ones directly responsible with receiving and sending the packets. This is the point of actually binding ZRTP to SC by using in these methods the specific ZRTP services provided by the ZRTP4J library which should be accessed through a ZRTPPacketManager class instance (which is empty at this moment).
  • A sole instance of this class is passed both to the input and the output stream by the ZRTPConnector, which fact provides the possibility to "communicate" between the read and write methods if needed or any other type of interaction between the input and output stream.
  • In the read and write methods, based on the information provided by the ZRTPManager about the ZRTP state, the streams may send RTP, SRTP or ZRTP packets (for SRTP is called the base class implementation - which I've tested).
  • The read and write methods have access to the SRTPTransformEngine to set and get the necessary info they need in the ZRTP communication. This is done by accessing the base class SRTPPacketTransformer member which may expose the SRTPTransformEngine through a getter.

This would be in rough lines my idea of integration. It's explained a bit more in detail in the comments inside the sources.

I don't know if it's ok or not. It might bring some limitations at some points, but I'm not so experienced to ZRTP to see exactly where now. I've tried to keep the SRTP-ZRTP coupling as low as possible. As it can be seen, all the idea is like practicaly adding a ZRTP separate layer, the only modifications I've done in the SRTP implementations being adding some getters and some setters for the derived classes.

Werner's approach after a basic look I've taken into the sources, is based on defining a ZRTPTransformEngine for the main part of the integration. This engine, as far as I can tell after a quick analysis, has pretty much the role I've imagined for my ZRTPPacketManager, so one option would be to adapt Werner's ZRTPEngine interaction to fit my approach related to ZRTPPacketManager (if it's a good approach, about which I have some doubts...) and "connect" the way I described, to the ZRTP library.

This is only an idea which might be taken into consideration :), but as said at start it may be also even better to try finding an integration way for ZRTP4J, based directly on Werner's current transform.zrtp package design (which doesn't seem to hard, but I still need to get some more things clear). Like I said, I still have a bit more to look on the sources to understand them better, and I'll try to think on the integration part also while doing that (maybe I'll get some ideas until the chat).

PS:

Sorry for not posting last evening, as I said I'll try in my mail. Have the bad habit of commenting the code after I finish a work phase, and this time the code comments took longer than I thought : ...

Tuesday, May 27, 2008

Activity Log : GSoC Week #04-#05 (12.V - 25.V)

Unfortunately I didn't have more than a weekend free these weeks so this entry will be quite short:
  • Regarding the problem I was talking about in my last post about how JMF (or FMJ) will handle the ZRTP packets, I think I've reached a conclusion, after I read the JMF samples here: http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/solutions/ (the RTP streaming section) and took another quick look into the JMF API Guide (which wasn't of very much help though because it doesn't contain the RTP Manager/Connector additions). As a reminder: the RTPConnector "acts" on the packets passed by the RTPManager before these are sent into network and on the receiver side, before these are passed to the receiver's RTPManager. So, I believe there shouldn't be a problem with the different ZRTP header (as I thought it might be) as long as all ZRTP traffic is being held in the boundary of a ZRTP RTPConnector dedicated implementation, in a similar way like SRTP is. Otherwise, if the packets would "reach" the RTPManager, there will be a problem probably with the unknown Format, resulting in the need of registering a new one, and things might get a bit to complicated. In conclusion, I think the idea of using a ZRTP dedicated Connector and consequently keeping most of the ZRTP management related to it remains the best option.
  • I also managed to make another comparison between the FMJ API and JMF one, on a few RTP related classes (did it once more at the start of GSoC), and as discussed on the dev list I can't find any differences (RTPConnector, RTPManager and few other classes included here). This, anyway, is only in rough API terms = looked at the function signatures provided by one and compared to the other. I decided to do this once more, after the problems Werner reported on the dev list with FMJ. I didn't manage to get deeper (I wanted actually to investigate a bit further about what are the differences related to the way ReceiveStreamEvent is handled - Werner's reported problem - between JMF and FMJ, but it seems that the JMF sources aren't available any longer on the Sun site: http://www.sun.com/software/communitysource/jmf/download.xml - eventually I'll look for them in other place). Anyway, as I said also on the mailing list, if the ZRTP solution will be based on the common API parts used by JMF and FMJ (which will be almost certain according to the comparison made above), it shouldn't be a problem on which of them is run and tested. Just as a fact, I personally did read a bit more about JMF in this first GSoC phase, so many assumptions are based on this knowledge - hope it applies on both of them (I tried to find some FMJ tutorials but there seems there aren't any - or I didn't look for them enough) .
  • The next steps: fortunately this week I'll be over with my exams (one more research project next Tuesday but that won't be a problem), and I'll finally be able to use most of my time for GSoC beginning with the next week, so probably this weekend (or next Monday latest) I'll try writing the starting code for the RTPConnector based ideas mentioned above. I still must talk to Werner about what exactly his library ZRTP4J provides and any integration issues related to this (probably also Monday) and must see how I'll use the UIService to connect the GUI to the Connector part. All these probably in my next activity log entry :).