PJSIP & CSipSimple for secure TLS VoIP calls

Frameworks & Libraries used :

Kamailio + TLS module (Server)
PJSIP (client)
CSipSimple (android wrapper)

For harnessing the TLS transport, SIP RFC 5922 under section 7.2 (https://tools.ietf.org/html/rfc5922#section-7.2) states that for securely identifying the SIP server, the server should marked as valid if their DNS name component matches the value in their entirety.
Since we were using a wild-card certificate for validating all sub-domains over SSL, the wild-card certificate was incapable of serving our purpose for SIP server validation.

We were left with two options :

1. Buy individual certificates for each of our DEV, STAGING & PRODUCTION environment SIP servers.
2. Buy a single PRODUCTION certificate with Subject Alternative Name (SAN) for DEV & STAGING environment.

We decided to go with the second approach since the product under development was nascent and has a few client deployments in production.

With CSipSimple, the next part was pretty simple. We enabled TLS & SRTP on the client side and configured the Kamailio server with the TLS module & RTPEngine for the same. With a few adjustments & tweaks the app was able to make secure VoIP calls through our SIP & RTP server.

A few basic implementations excerpts :

Adding a profile in CSipSimple with TLS enabled :

SipProfile profile = new SipProfile();

profile.display_name = "YOUR PROJECT NAME";
profile.id = existingProfileId;
profile.acc_id = "";
profile.reg_uri = "sip:" + USERNAME;
profile.realm = "*";
profile.username = USERNAME;
profile.data = PASSWORD;
profile.proxies = new String[] { "sip:" + DOMAIN.COM };
profile.scheme = SipProfile.CRED_SCHEME_DIGEST;
profile.datatype = SipProfile.CRED_DATA_PLAIN_PASSWD;
profile.reg_timeout = 630;
profile.reg_delay_before_refresh = 30;
profile.transport = SipProfile.TRANSPORT_TLS;

ContentValues values = profile.getDbContentValues();

if (existingProfileId != SipProfile.INVALID_ID)
 {
         getContentResolver().update(ContentUris.withAppendedId(SipProfile.ACCOUNT_ID_URI_ BASE,existingProfileId), values, null, null);
  }
else
 {
         Uri savedUri = getContentResolver().insert(SipProfile.ACCOUNT_URI,values);
         if (savedUri != null) 
         {
               existingProfileId = ContentUris.parseId(savedUri);
         }
  }


Configuring certificate for TLS:

SipConfigManager.setPreferenceStringValue(this,
SipConfigManager.CERT_FILE,"PATH TO CERTIFICATE PEM FILE");
SipConfigManager.setPreferenceStringValue(this,
SipConfigManager.PRIVKEY_FILE,"PATH TO CERTIFICATE KEY FILE");


Podcast

Michael Patterson sat down with the CEO of Boston Byte, Mustapha Shaikh to discuss the significance and rapid digitization of the healthcar...