#13795: Initial commit for sflphone-android
includes: libexpat libyaml libdbus-c++ commoncpp ccrtp
libdbus (from android-4.0.4 sources)
TODO:
- git ignores "/jni/sflphone", sflphone repo should be cloned.
- sflphone-android only needs daemon directory. Ideally it should be possible
to clone it without cloning the whole sflphone project.
into sfl-android (commit 6a0fa7a "#13961: Fix cipher handling" has been used here)
- add pjsip-android project as a git submodule
- sflphone-android needs pjsip android project. Ideally daemon git repository
should not embed pjsip. Instead pjsip should be clone from official repositories.
Considering this, structure should have three distincts git repos:
sflphone-android/.git
sflphone-android/jni/ccrtp-1.8.0-android
sflphone-android/jni/commoncpp2-1.8.1-android
sflphone-android/jni/dbus
sflphone-android/jni/libdbus-c++-0.9.0-android
sflphone-android/jni/libexpat
sflphone-android/jni/libyaml
sflphone-android/jni/sflphone-daemon/.git
sflphone-android/jni/sflphone-daemon/src/audio
sflphone-android/jni/sflphone-daemon/src/config
sflphone-android/jni/sflphone-daemon/src/dbus
sflphone-android/jni/sflphone-daemon/src/history
sflphone-android/jni/sflphone-daemon/src/hooks
sflphone-android/jni/sflphone-daemon/src/iax
sflphone-android/jni/sflphone-daemon/src/sip
sflphone-android/jni/sflphone-daemon/src/video
sflphone-android/jni/pjsip-android/.git
Signed-off-by: Emeric Vigier <emeric.vigier@savoirfairelinux.com>
diff --git a/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/InitializeGcrypt.cxx b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/InitializeGcrypt.cxx
new file mode 100755
index 0000000..6d23d08
--- /dev/null
+++ b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/InitializeGcrypt.cxx
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2006 Werner Dittmann
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Boston, MA 02111.
+*/
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <gcrypt.h>
+
+/*
+ * The following macro was copied from gcrypt.h and modified to explicitly
+ * cast the pointer types to keep the compiler happy.
+ */
+#define GCRY_THREAD_OPTION_PTHREAD_CPP_IMPL \
+static int gcry_pthread_mutex_init (void **priv) \
+{ \
+ int err = 0; \
+ pthread_mutex_t *lock = (pthread_mutex_t *)malloc (sizeof (pthread_mutex_t)); \
+ \
+ if (!lock) \
+ err = ENOMEM; \
+ if (!err) \
+{ \
+ err = pthread_mutex_init (lock, NULL); \
+ if (err) \
+ free (lock); \
+ else \
+ *priv = lock; \
+} \
+ return err; \
+} \
+static int gcry_pthread_mutex_destroy (void **lock) \
+{ int err = pthread_mutex_destroy ((pthread_mutex_t *)*lock); free (*lock); return err; } \
+static int gcry_pthread_mutex_lock (void **lock) \
+{ return pthread_mutex_lock ((pthread_mutex_t *)*lock); } \
+static int gcry_pthread_mutex_unlock (void **lock) \
+{ return pthread_mutex_unlock ((pthread_mutex_t *)*lock); } \
+ \
+static struct gcry_thread_cbs gcry_threads_pthread = \
+{ GCRY_THREAD_OPTION_PTHREAD, NULL, \
+ gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, \
+ gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock }
+
+/** Implement the locking callback functions for libgcrypt.
+ *
+ */
+
+static int initialized = 0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+GCRY_THREAD_OPTION_PTHREAD_CPP_IMPL;
+#ifdef __cplusplus
+}
+#endif
+
+int initializeGcrypt ()
+{
+
+ if (initialized) {
+ return 1;
+ }
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ gcry_check_version(NULL);
+ gcry_control(GCRYCTL_DISABLE_SECMEM);
+ initialized = 1;
+ return 1;
+}
diff --git a/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcryptAesSrtp.cxx b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcryptAesSrtp.cxx
new file mode 100644
index 0000000..1188633
--- /dev/null
+++ b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcryptAesSrtp.cxx
@@ -0,0 +1,292 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+*/
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * @author Johan Bilien <jobi@via.ecp.fr>
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+extern void initializeGcrypt();
+
+#include <gcrypt.h> // the include of gcrypt
+#include <stdlib.h>
+#include <ccrtp/crypto/AesSrtp.h>
+
+#include <stdio.h>
+
+AesSrtp::AesSrtp(int algo) : key(NULL), algorithm(algo) {
+ initializeGcrypt();
+}
+
+AesSrtp::AesSrtp( uint8* k, int32 keyLength, int algo) :
+ key(NULL), algorithm(algo) {
+
+ initializeGcrypt();
+ setNewKey(k, keyLength);
+}
+
+AesSrtp::~AesSrtp() {
+ if (key) {
+ gcry_cipher_close(static_cast<gcry_cipher_hd_t>(key));
+ key = NULL;
+ }
+}
+
+bool AesSrtp::setNewKey(const uint8* k, int32 keyLength) {
+
+ // release an existing key before setting a new one
+ if (key != NULL) {
+ gcry_cipher_close(static_cast<gcry_cipher_hd_t>(key));
+ key = NULL;
+ }
+
+ int algo = 0;
+ if (keyLength == 16) {
+ algo = GCRY_CIPHER_AES;
+ }
+ else if (keyLength == 32) {
+ algo = GCRY_CIPHER_AES256;
+ }
+ else {
+ return false;
+ }
+ gcry_cipher_hd_t tmp;
+ int err = gcry_cipher_open(&tmp, algo, GCRY_CIPHER_MODE_ECB, 0);
+ key = tmp;
+ err = gcry_cipher_setkey(static_cast<gcry_cipher_hd_t>(key), k, keyLength);
+ return true;
+}
+
+
+void AesSrtp::encrypt( const uint8* input, uint8* output ) {
+ if (key != NULL) {
+ gcry_cipher_encrypt (static_cast<gcry_cipher_hd_t>(key),
+ output, SRTP_BLOCK_SIZE, input, SRTP_BLOCK_SIZE);
+ }
+}
+
+void AesSrtp::get_ctr_cipher_stream( uint8* output, uint32 length,
+ uint8* iv ) {
+ uint16 ctr;
+ uint16 input;
+
+ unsigned char aes_input[SRTP_BLOCK_SIZE];
+ unsigned char temp[SRTP_BLOCK_SIZE];
+
+ memcpy(aes_input, iv, 14 );
+ iv += 14;
+
+ for( ctr = 0; ctr < length/SRTP_BLOCK_SIZE; ctr++ ){
+ input = ctr;
+ //compute the cipher stream
+ aes_input[14] = (uint8)((input & 0xFF00) >> 8);
+ aes_input[15] = (uint8)((input & 0x00FF));
+
+ gcry_cipher_encrypt(static_cast<gcry_cipher_hd_t>(key), &output[ctr*SRTP_BLOCK_SIZE], SRTP_BLOCK_SIZE,
+ aes_input, SRTP_BLOCK_SIZE);
+ }
+ if ((length % SRTP_BLOCK_SIZE) > 0) {
+ // Treat the last bytes:
+ input = ctr;
+ aes_input[14] = (uint8)((input & 0xFF00) >> 8);
+ aes_input[15] = (uint8)((input & 0x00FF));
+
+ gcry_cipher_encrypt(static_cast<gcry_cipher_hd_t>(key), temp, SRTP_BLOCK_SIZE, aes_input, SRTP_BLOCK_SIZE);
+ memcpy(&output[ctr*SRTP_BLOCK_SIZE], temp, length % SRTP_BLOCK_SIZE);
+ }
+}
+
+
+void AesSrtp::ctr_encrypt( const uint8* input, uint32 input_length,
+ uint8* output, uint8* iv ) {
+
+ if (key == NULL)
+ return;
+
+ uint8* cipher_stream = new uint8[input_length];
+
+ get_ctr_cipher_stream( cipher_stream, input_length, iv );
+
+ for( unsigned int i = 0; i < input_length; i++ ){
+ output[i] = cipher_stream[i] ^ input[i];
+ }
+ delete []cipher_stream;
+}
+
+void AesSrtp::ctr_encrypt( uint8* data, uint32 data_length, uint8* iv ) {
+
+ if (key == NULL)
+ return;
+
+ //unsigned char cipher_stream[data_length];
+ uint8* cipher_stream = new uint8[data_length];
+
+ get_ctr_cipher_stream( cipher_stream, data_length, iv );
+
+ for( uint32 i = 0; i < data_length; i++ ){
+ data[i] ^= cipher_stream[i];
+ }
+ delete[] cipher_stream;
+}
+
+void AesSrtp::f8_encrypt(const uint8* data, uint32 data_length,
+ uint8* iv, uint8* origKey, int32 keyLen,
+ uint8* salt, int32 saltLen, AesSrtp* f8Cipher ) {
+
+ f8_encrypt(data, data_length, const_cast<uint8*>(data), iv, origKey, keyLen, salt, saltLen, f8Cipher);
+}
+
+#define MAX_KEYLEN 32
+
+void AesSrtp::f8_encrypt(const uint8* in, uint32 in_length, uint8* out,
+ uint8* iv, uint8* origKey, int32 keyLen,
+ uint8* salt, int32 saltLen, AesSrtp* f8Cipher ) {
+
+
+ unsigned char *cp_in, *cp_in1, *cp_out;
+ int i;
+ int offset = 0;
+
+ unsigned char ivAccent[SRTP_BLOCK_SIZE];
+ unsigned char maskedKey[MAX_KEYLEN];
+ unsigned char saltMask[MAX_KEYLEN];
+ unsigned char S[SRTP_BLOCK_SIZE];
+
+ F8_CIPHER_CTX f8ctx;
+
+ if (key == NULL)
+ return;
+
+ if (keyLen > MAX_KEYLEN)
+ return;
+
+ if (saltLen > keyLen)
+ return;
+
+ /*
+ * Get memory for the derived IV (IV')
+ */
+ f8ctx.ivAccent = ivAccent;
+
+ /*
+ * First copy the salt into the mask field, then fill with 0x55 to
+ * get a full key.
+ */
+ memcpy(saltMask, salt, saltLen);
+ memset(saltMask+saltLen, 0x55, keyLen-saltLen);
+
+ /*
+ * XOR the original key with the above created mask to
+ * get the special key.
+ */
+ cp_out = maskedKey;
+ cp_in = origKey;
+ cp_in1 = saltMask;
+ for (i = 0; i < keyLen; i++) {
+ *cp_out++ = *cp_in++ ^ *cp_in1++;
+ }
+ /*
+ * Prepare the a new AES cipher with the special key to compute IV'
+ */
+ f8Cipher->setNewKey(maskedKey, keyLen);
+
+ /*
+ * Use the masked key to encrypt the original IV to produce IV'.
+ *
+ * After computing the IV' we don't need this cipher context anymore, free it.
+ */
+ f8Cipher->encrypt(iv, f8ctx.ivAccent);
+
+ f8ctx.J = 0; // initialize the counter
+ f8ctx.S = S; // get the key stream buffer
+
+ memset(f8ctx.S, 0, SRTP_BLOCK_SIZE); // initial value for key stream
+
+ while (in_length >= SRTP_BLOCK_SIZE) {
+ processBlock(&f8ctx, in+offset, SRTP_BLOCK_SIZE, out+offset);
+ in_length -= SRTP_BLOCK_SIZE;
+ offset += SRTP_BLOCK_SIZE;
+ }
+ if (in_length > 0) {
+ processBlock(&f8ctx, in+offset, in_length, out+offset);
+ }
+}
+
+int AesSrtp::processBlock(F8_CIPHER_CTX *f8ctx, const uint8* in, int32 length, uint8* out) {
+
+ int i;
+ const uint8 *cp_in;
+ uint8* cp_in1, *cp_out;
+ uint32_t *ui32p;
+
+ /*
+ * XOR the previous key stream with IV'
+ * ( S(-1) xor IV' )
+ */
+ cp_in = f8ctx->ivAccent;
+ cp_out = f8ctx->S;
+ for (i = 0; i < SRTP_BLOCK_SIZE; i++) {
+ *cp_out++ ^= *cp_in++;
+ }
+ /*
+ * Now XOR (S(n-1) xor IV') with the current counter, then increment the counter
+ */
+ ui32p = (uint32_t *)f8ctx->S;
+ ui32p[3] ^= htonl(f8ctx->J);
+ f8ctx->J++;
+ /*
+ * Now compute the new key stream using AES encrypt
+ */
+ gcry_cipher_encrypt(static_cast<gcry_cipher_hd_t>(key), f8ctx->S, SRTP_BLOCK_SIZE, NULL, 0);
+ /*
+ * as the last step XOR the plain text with the key stream to produce
+ * the ciphertext.
+ */
+ cp_out = out;
+ cp_in = in;
+ cp_in1 = f8ctx->S;
+ for (i = 0; i < length; i++) {
+ *cp_out++ = *cp_in++ ^ *cp_in1++;
+ }
+ return length;
+}
+
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
+
+
diff --git a/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcrypthmac.cxx b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcrypthmac.cxx
new file mode 100644
index 0000000..c13f657
--- /dev/null
+++ b/jni/ccrtp-1.8.0-android/src/ccrtp/crypto/gcrypt/gcrypthmac.cxx
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ */
+#include <gcrypt.h>
+
+#include <ccrtp/crypto/hmac.h>
+#include <stdio.h>
+
+void hmac_sha1(uint8* key, int32 keyLength,
+ const uint8* data, int32 dataLength,
+ uint8* mac, int32* macLength)
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ gcry_md_write (hd, data, dataLength);
+
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA1);
+ memcpy(mac, p, SHA1_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA1_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
+
+void hmac_sha1( uint8* key, int32 keyLength,
+ const uint8* dataChunks[],
+ uint32 dataChunkLength[],
+ uint8* mac, int32* macLength )
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA1);
+ memcpy(mac, p, SHA1_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA1_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
+
+void* createSha1HmacContext(uint8_t* key, int32_t key_length)
+{
+ gcry_md_hd_t ctx;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(ctx, key, key_length);
+ return ctx;
+}
+
+void hmacSha1Ctx(void* ctx, const uint8_t* data, uint32_t data_length,
+ uint8_t* mac, int32_t* mac_length)
+{
+ gcry_md_hd_t pctx = (gcry_md_hd_t)ctx;
+
+ gcry_md_reset(pctx);
+
+ gcry_md_write (pctx, data, data_length);
+
+ uint8_t* p = gcry_md_read (pctx, GCRY_MD_SHA1);
+ memcpy(mac, p, SHA1_DIGEST_LENGTH);
+ if (mac_length != NULL) {
+ *mac_length = SHA1_DIGEST_LENGTH;
+ }
+}
+
+void hmacSha1Ctx(void* ctx, const uint8_t* data[], uint32_t data_length[],
+ uint8_t* mac, int32_t* mac_length )
+{
+ gcry_md_hd_t pctx = (gcry_md_hd_t)ctx;
+
+ gcry_md_reset (pctx);
+ while (*data) {
+ gcry_md_write (pctx, *data, (uint32)(*data_length));
+ data++;
+ data_length++;
+ }
+ uint8_t* p = gcry_md_read (pctx, GCRY_MD_SHA1);
+ memcpy(mac, p, SHA1_DIGEST_LENGTH);
+ if (mac_length != NULL) {
+ *mac_length = SHA1_DIGEST_LENGTH;
+ }
+}
+
+void freeSha1HmacContext(void* ctx)
+{
+ gcry_md_hd_t pctx = (gcry_md_hd_t)ctx;
+ gcry_md_close (pctx);
+}
\ No newline at end of file