diff --git a/src/native/openssl/BlockCipher.c b/src/native/openssl/BlockCipher.c deleted file mode 100644 index 84518018b..000000000 --- a/src/native/openssl/BlockCipher.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BlockCipher.h" - -#include -#include -#include - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_aes_128_ecb - * Signature: ()J - */ -JNIEXPORT jlong JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1aes_1128_1ecb - (JNIEnv *env, jclass clazz) -{ - return (jlong) (intptr_t) EVP_aes_128_ecb(); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_block_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1block_1size - (JNIEnv *env, jclass clazz, jlong e) -{ - return EVP_CIPHER_block_size((const EVP_CIPHER *) (intptr_t) e); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_cleanup - * Signature: (J)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1cleanup - (JNIEnv *env, jclass clazz, jlong a) -{ - return EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX *) (intptr_t) a); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_create - * Signature: ()J - */ -JNIEXPORT jlong JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1create - (JNIEnv *env, jclass clazz) -{ - EVP_CIPHER_CTX *ctx = malloc(sizeof(EVP_CIPHER_CTX)); - - if (ctx) - EVP_CIPHER_CTX_init(ctx); - return (jlong) (intptr_t) ctx; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_destroy - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1destroy - (JNIEnv *env, jclass clazz, jlong ctx) -{ - EVP_CIPHER_CTX *ctx_ = (EVP_CIPHER_CTX *) (intptr_t) ctx; - - EVP_CIPHER_CTX_cleanup(ctx_); - free(ctx_); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_set_padding - * Signature: (JZ)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1set_1padding - (JNIEnv *env, jclass clazz, jlong x, jboolean padding) -{ - return EVP_CIPHER_CTX_set_padding((EVP_CIPHER_CTX *) (intptr_t) x, padding); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherFinal_ex - * Signature: (J[BII)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherFinal_1ex - (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray out, jint outOff, - jint outl) -{ - jbyte *out_ = (*env)->GetPrimitiveArrayCritical(env, out, NULL); - int i; - - if (out_) - { - int outl_ = outl; - - i - = EVP_CipherFinal_ex( - (EVP_CIPHER_CTX *) (intptr_t) ctx, - (unsigned char *) (out_ + outOff), - &outl_); - (*env)->ReleasePrimitiveArrayCritical(env, out, out_, 0); - i = i ? outl_ : -1; - } - else - { - i = -1; - } - return i; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherInit_ex - * Signature: (JJJ[B[BI)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherInit_1ex - (JNIEnv *env, jclass clazz, jlong ctx, jlong type, jlong impl, - jbyteArray key, jbyteArray iv, jint enc) -{ - jbyte *key_; - jboolean ok; - - if (key) - { - key_ = (*env)->GetPrimitiveArrayCritical(env, key, NULL); - ok = key_ ? JNI_TRUE : JNI_FALSE; - } - else - { - key_ = NULL; - ok = JNI_TRUE; - } - if (JNI_TRUE == ok) - { - jbyte *iv_; - - if (iv) - { - iv_ = (*env)->GetPrimitiveArrayCritical(env, iv, NULL); - ok = iv_ ? JNI_TRUE : JNI_FALSE; - } - else - { - iv_ = NULL; - ok = JNI_TRUE; - } - if (JNI_TRUE == ok) - { - ok - = EVP_CipherInit_ex( - (EVP_CIPHER_CTX *) (intptr_t) ctx, - (const EVP_CIPHER *) (intptr_t) type, - (ENGINE *) (intptr_t) impl, - (unsigned char *) key_, - (unsigned char *) iv_, - enc); - if (iv_) - (*env)->ReleasePrimitiveArrayCritical(env, iv, iv_, JNI_ABORT); - } - if (key_) - (*env)->ReleasePrimitiveArrayCritical(env, key, key_, JNI_ABORT); - } - return ok; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherUpdate - * Signature: (J[BII[BII)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherUpdate__J_3BII_3BII - (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray out, jint outOff, - jint outl, jbyteArray in, jint inOff, jint inl) -{ - jbyte *out_ = (*env)->GetPrimitiveArrayCritical(env, out, NULL); - int i; - - if (out_) - { - jbyte *in_ = (*env)->GetPrimitiveArrayCritical(env, in, NULL); - - if (in_) - { - int outl_ = outl; - - i - = EVP_CipherUpdate( - (EVP_CIPHER_CTX *) (intptr_t) ctx, - (unsigned char *) (out_ + outOff), &outl_, - (unsigned char *) (in_ + inOff), inl); - (*env)->ReleasePrimitiveArrayCritical(env, in, in_, JNI_ABORT); - i = i ? outl_ : -1; - } - else - { - i = -1; - } - (*env)->ReleasePrimitiveArrayCritical(env, out, out_, 0); - } - else - { - i = -1; - } - return i; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherUpdate - * Signature: (JLjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherUpdate__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2II - (JNIEnv *env, jclass clazz, jlong ctx, jobject out, jint outOff, jint outl, - jobject in, jint inOff, jint inl) -{ - unsigned char *out_ = (*env)->GetDirectBufferAddress(env, out); - int i; - - if (out_) - { - unsigned char *in_ = (*env)->GetDirectBufferAddress(env, in); - - if (in_) - { - int outl_ = outl; - - i - = EVP_CipherUpdate( - (EVP_CIPHER_CTX *) (intptr_t) ctx, - out_ + outOff, &outl_, - in_ + inOff, inl); - i = i ? outl_ : -1; - } - else - { - i = -1; - } - } - else - { - i = -1; - } - return i; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_get_cipherbyname - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1get_1cipherbyname - (JNIEnv *env, jclass clazz, jstring name) -{ - const char *name_ = (*env)->GetStringUTFChars(env, name, NULL); - const EVP_CIPHER *cipher; - - if (name_) - { - cipher = EVP_get_cipherbyname(name_); - if (!cipher) - { - /* - * The cipher table must be initialized using, for example, the - * function OpenSSL_add_all_ciphers, for the function - * EVP_get_cipherbyname to work. - */ - OpenSSL_add_all_ciphers(); - cipher = EVP_get_cipherbyname(name_); - } - (*env)->ReleaseStringUTFChars(env, name, name_); - } - else - { - cipher = NULL; - } - return (jlong) (intptr_t) cipher; -} diff --git a/src/native/openssl/BlockCipher.h b/src/native/openssl/BlockCipher.h deleted file mode 100644 index 29967b46b..000000000 --- a/src/native/openssl/BlockCipher.h +++ /dev/null @@ -1,101 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher */ - -#ifndef _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher -#define _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_aes_128_ecb - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1aes_1128_1ecb - (JNIEnv *, jclass); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_block_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1block_1size - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_cleanup - * Signature: (J)Z - */ -JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1cleanup - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_create - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1create - (JNIEnv *, jclass); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_destroy - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1destroy - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CIPHER_CTX_set_padding - * Signature: (JZ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CIPHER_1CTX_1set_1padding - (JNIEnv *, jclass, jlong, jboolean); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherFinal_ex - * Signature: (J[BII)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherFinal_1ex - (JNIEnv *, jclass, jlong, jbyteArray, jint, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherInit_ex - * Signature: (JJJ[B[BI)Z - */ -JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherInit_1ex - (JNIEnv *, jclass, jlong, jlong, jlong, jbyteArray, jbyteArray, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherUpdate - * Signature: (J[BII[BII)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherUpdate__J_3BII_3BII - (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jbyteArray, jint, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_CipherUpdate - * Signature: (JLjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1CipherUpdate__JLjava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2II - (JNIEnv *, jclass, jlong, jobject, jint, jint, jobject, jint, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher - * Method: EVP_get_cipherbyname - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLBlockCipher_EVP_1get_1cipherbyname - (JNIEnv *, jclass, jstring); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/native/openssl/Digest.c b/src/native/openssl/Digest.c deleted file mode 100644 index 10707d35b..000000000 --- a/src/native/openssl/Digest.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Digest.h" - -#include -#include - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestFinal_ex - * Signature: (J[BI)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestFinal_1ex - (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray md, jint off) -{ - jbyte *md_ = (*env)->GetPrimitiveArrayCritical(env, md, NULL); - int i; - - if (md_) - { - unsigned int s = 0; - - i - = EVP_DigestFinal_ex( - (EVP_MD_CTX *) (intptr_t) ctx, - (unsigned char *) (md_ + off), - &s); - (*env)->ReleasePrimitiveArrayCritical(env, md, md_, 0); - i = i ? ((int) s) : -1; - } - else - { - i = -1; - } - return i; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestInit_ex - * Signature: (JJJ)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestInit_1ex - (JNIEnv *env, jclass clazz, jlong ctx, jlong type, jlong impl) -{ - return - EVP_DigestInit_ex( - (EVP_MD_CTX *) (intptr_t) ctx, - (const EVP_MD *) (intptr_t) type, - (ENGINE *) (intptr_t) impl); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestUpdate - * Signature: (J[BII)Z - */ -JNIEXPORT jboolean JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestUpdate - (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray d, jint off, jint cnt) -{ - jbyte *d_ = (*env)->GetPrimitiveArrayCritical(env, d, NULL); - jboolean ok; - - if (d_) - { - ok = EVP_DigestUpdate((EVP_MD_CTX *) (intptr_t) ctx, d_ + off, cnt); - (*env)->ReleasePrimitiveArrayCritical(env, d, d_, JNI_ABORT); - } - else - { - ok = JNI_FALSE; - } - return ok; -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_block_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1block_1size - (JNIEnv *env, jclass clazz, jlong ctx) -{ - return EVP_MD_CTX_block_size((const EVP_MD_CTX *) (intptr_t) ctx); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_create - * Signature: ()J - */ -JNIEXPORT jlong JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1create - (JNIEnv *env, jclass clazz) -{ - return (jlong) (intptr_t) EVP_MD_CTX_create(); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_destroy - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1destroy - (JNIEnv *env, jclass clazz, jlong ctx) -{ - EVP_MD_CTX_destroy((EVP_MD_CTX *) (intptr_t) ctx); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1size - (JNIEnv *env, jclass clazz, jlong ctx) -{ - return EVP_MD_CTX_size((const EVP_MD_CTX *) (intptr_t) ctx); -} - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_sha1 - * Signature: ()J - */ -JNIEXPORT jlong JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1sha1 - (JNIEnv *env, jclass clazz) -{ - return (jlong) (intptr_t) EVP_sha1(); -} diff --git a/src/native/openssl/Digest.h b/src/native/openssl/Digest.h deleted file mode 100644 index f79df6acd..000000000 --- a/src/native/openssl/Digest.h +++ /dev/null @@ -1,77 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest */ - -#ifndef _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest -#define _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestFinal_ex - * Signature: (J[BI)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestFinal_1ex - (JNIEnv *, jclass, jlong, jbyteArray, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestInit_ex - * Signature: (JJJ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestInit_1ex - (JNIEnv *, jclass, jlong, jlong, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_DigestUpdate - * Signature: (J[BII)Z - */ -JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestUpdate - (JNIEnv *, jclass, jlong, jbyteArray, jint, jint); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_block_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1block_1size - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_create - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1create - (JNIEnv *, jclass); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_destroy - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1destroy - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_MD_CTX_size - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1MD_1CTX_1size - (JNIEnv *, jclass, jlong); - -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest - * Method: EVP_sha1 - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1sha1 - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/native/openssl/HMAC.c b/src/native/openssl/HMAC.c index ca8a99709..1ac0dc207 100644 --- a/src/native/openssl/HMAC.c +++ b/src/native/openssl/HMAC.c @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "Digest.h" +#include "HMAC.h" #include #include @@ -45,18 +45,6 @@ Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_EVP_1sha1 return (jlong) (intptr_t) EVP_sha1(); } -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC - * Method: HMAC_CTX_cleanup - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_HMAC_1CTX_1cleanup - (JNIEnv *env, jclass clazz, jlong ctx) -{ - HMAC_CTX_cleanup((HMAC_CTX *) (intptr_t) ctx); -} - /* * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC * Method: HMAC_CTX_create diff --git a/src/native/openssl/HMAC.h b/src/native/openssl/HMAC.h index 225dfc4b6..6be14edb7 100644 --- a/src/native/openssl/HMAC.h +++ b/src/native/openssl/HMAC.h @@ -23,14 +23,6 @@ JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_E JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_EVP_1sha1 (JNIEnv *, jclass); -/* - * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC - * Method: HMAC_CTX_cleanup - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_HMAC_1CTX_1cleanup - (JNIEnv *, jclass, jlong); - /* * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC * Method: HMAC_CTX_create diff --git a/src/native/openssl/OpenSSLWrapperLoader.c b/src/native/openssl/OpenSSLWrapperLoader.c new file mode 100644 index 000000000..33e5b7ad8 --- /dev/null +++ b/src/native/openssl/OpenSSLWrapperLoader.c @@ -0,0 +1,35 @@ +/* + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OpenSSLWrapperLoader.h" +#include +#include + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader + * Method: OpenSSL_Init + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader_OpenSSL_1Init + (JNIEnv *env, jclass clazz) +{ + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + return JNI_TRUE; +} + diff --git a/src/native/openssl/OpenSSLWrapperLoader.h b/src/native/openssl/OpenSSLWrapperLoader.h new file mode 100644 index 000000000..6a6b0fbee --- /dev/null +++ b/src/native/openssl/OpenSSLWrapperLoader.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader */ + +#ifndef _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader +#define _Included_org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader + * Method: OpenSSL_Init + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLWrapperLoader_OpenSSL_1Init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/native/openssl/SRTPCipherCTROpenSSL.c b/src/native/openssl/SRTPCipherCTROpenSSL.c new file mode 100644 index 000000000..d87f4183d --- /dev/null +++ b/src/native/openssl/SRTPCipherCTROpenSSL.c @@ -0,0 +1,108 @@ +/* + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SRTPCipherCTROpenSSL.h" + +#include +#include +#include + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1create + (JNIEnv *env, jclass clazz) +{ + EVP_CIPHER_CTX *ctx = malloc(sizeof(EVP_CIPHER_CTX)); + if (ctx) + EVP_CIPHER_CTX_init(ctx); + + return (jlong) (intptr_t) ctx; +} + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1destroy + (JNIEnv *env, jclass clazz, jlong ctx) +{ + if (ctx) { + EVP_CIPHER_CTX *ctx_ = (EVP_CIPHER_CTX *) (intptr_t) ctx; + EVP_CIPHER_CTX_cleanup(ctx_); + free(ctx_); + } +} + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_init + * Signature: (J[B)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1init + (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray key) +{ + unsigned char key_[16]; + (*env)->GetByteArrayRegion(env, key, 0, 16, key_); + return EVP_CipherInit_ex((EVP_CIPHER_CTX *) (intptr_t) ctx, EVP_aes_128_ctr(), NULL, key_, NULL, 1); +} + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_process + * Signature: (J[B[BII)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1process + (JNIEnv *env, jclass clazz, jlong ctx, jbyteArray iv, jbyteArray inOut, jint offset, jint len) +{ + int ok = 0; + unsigned char iv_[16]; + (*env)->GetByteArrayRegion(env, iv, 0, 16, iv_); + jbyte *inOut_; + inOut_ = (*env)->GetPrimitiveArrayCritical(env, inOut, NULL); + if (!inOut) + goto exit; + + ok = EVP_CipherInit_ex( + (EVP_CIPHER_CTX *) (intptr_t) ctx, + NULL, + NULL, + NULL, + iv_, + -1); + if(ok == 0) + goto exit; + + int len_ = len; + ok = EVP_CipherUpdate( + (EVP_CIPHER_CTX *) (intptr_t) ctx, + (unsigned char *) (inOut_ + offset), &len_, + (unsigned char *) (inOut_ + offset), len); + +exit: + if (inOut_) + (*env)->ReleasePrimitiveArrayCritical(env, inOut, inOut_, 0); + + return ok; +} + diff --git a/src/native/openssl/SRTPCipherCTROpenSSL.h b/src/native/openssl/SRTPCipherCTROpenSSL.h new file mode 100644 index 000000000..e25d965fb --- /dev/null +++ b/src/native/openssl/SRTPCipherCTROpenSSL.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL */ + +#ifndef _Included_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL +#define _Included_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_create + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1create + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_destroy + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_init + * Signature: (J[B)Z + */ +JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1init + (JNIEnv *, jclass, jlong, jbyteArray); + +/* + * Class: org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL + * Method: AES128CTR_CTX_process + * Signature: (J[B[BII)Z + */ +JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_transform_srtp_SRTPCipherCTROpenSSL_AES128CTR_1CTX_1process + (JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/AES.java b/src/org/jitsi/impl/neomedia/transform/srtp/AES.java index 19e75dca7..4dead4c70 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/AES.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/AES.java @@ -89,7 +89,6 @@ public class AES private static final Class[] FACTORY_CLASSES = { BouncyCastleBlockCipherFactory.class, - OpenSSLBlockCipherFactory.class, SunJCEBlockCipherFactory.class, SunPKCS11BlockCipherFactory.class, }; @@ -645,25 +644,6 @@ public BlockCipher createBlockCipher() } } - /** - * Implements BlockCipherFactory using OpenSSL. - * - * @author Lyubomir Marinov - */ - public static class OpenSSLBlockCipherFactory - implements BlockCipherFactory - { - /** - * {@inheritDoc} - */ - @Override - public BlockCipher createBlockCipher() - throws Exception - { - return new OpenSSLBlockCipher(OpenSSLBlockCipher.AES_128_ECB); - } - } - /** * Implements BlockCipherFactory using Sun JCE. * diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/BaseSRTPCryptoContext.java b/src/org/jitsi/impl/neomedia/transform/srtp/BaseSRTPCryptoContext.java index 4a21f84e5..3066be05a 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/BaseSRTPCryptoContext.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/BaseSRTPCryptoContext.java @@ -77,20 +77,15 @@ class BaseSRTPCryptoContext */ protected final byte[] authKey; - /** - * The symmetric cipher engines we need here - */ - protected final BlockCipher cipher; - /** * implements the counter cipher mode for RTP according to RFC 3711 */ - protected final SRTPCipherCTR cipherCtr = new SRTPCipherCTR(); + protected final SRTPCipherCTR cipherCtr; /** - * Used inside F8 mode only + * F8 mode cipher */ - protected final BlockCipher cipherF8; + protected final SRTPCipherF8 cipherF8; /** * Derived session encryption key @@ -163,7 +158,7 @@ protected BaseSRTPCryptoContext(int ssrc) this.ssrc = ssrc; authKey = null; - cipher = null; + cipherCtr = null; cipherF8 = null; encKey = null; mac = null; @@ -194,8 +189,8 @@ protected BaseSRTPCryptoContext( masterSalt = new byte[saltKeyLength]; System.arraycopy(masterS, 0, masterSalt, 0, saltKeyLength); - BlockCipher cipher = null; - BlockCipher cipherF8 = null; + SRTPCipherCTR cipherCtr = null; + SRTPCipherF8 cipherF8 = null; byte[] encKey = null; byte[] saltKey = null; @@ -205,26 +200,33 @@ protected BaseSRTPCryptoContext( break; case SRTPPolicy.AESF8_ENCRYPTION: - cipherF8 = AES.createBlockCipher(); + cipherF8 = new SRTPCipherF8(AES.createBlockCipher()); //$FALL-THROUGH$ case SRTPPolicy.AESCM_ENCRYPTION: - cipher = AES.createBlockCipher(); + if (OpenSSLWrapperLoader.isLoaded()) + { + cipherCtr = new SRTPCipherCTROpenSSL(); + } + else + { + cipherCtr = new SRTPCipherCTRJava(AES.createBlockCipher()); + } encKey = new byte[encKeyLength]; saltKey = new byte[saltKeyLength]; break; case SRTPPolicy.TWOFISHF8_ENCRYPTION: - cipherF8 = new TwofishEngine(); + cipherF8 = new SRTPCipherF8(new TwofishEngine()); //$FALL-THROUGH$ case SRTPPolicy.TWOFISH_ENCRYPTION: - cipher = new TwofishEngine(); + cipherCtr = new SRTPCipherCTRJava(new TwofishEngine()); encKey = new byte[encKeyLength]; saltKey = new byte[saltKeyLength]; break; } - this.cipher = cipher; + this.cipherCtr = cipherCtr; this.cipherF8 = cipherF8; this.encKey = encKey; this.saltKey = saltKey; diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/CryptoBenchmark.java b/src/org/jitsi/impl/neomedia/transform/srtp/CryptoBenchmark.java index 6688de829..56e7bab65 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/CryptoBenchmark.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/CryptoBenchmark.java @@ -60,7 +60,6 @@ else if ("-nio-block-cipher".equalsIgnoreCase(arg)) Digest[] digests = { new SHA1Digest(), - new OpenSSLDigest(OpenSSLDigest.SHA1) }; MessageDigest[] messageDigests = { @@ -108,8 +107,7 @@ else if ("-nio-block-cipher".equalsIgnoreCase(arg)) new BlockCipherAdapter( Cipher.getInstance("AES_128/ECB/NoPadding", sunPKCS11)), new BlockCipherAdapter( - Cipher.getInstance("AES_128/ECB/NoPadding", sunJCE)), - new OpenSSLBlockCipher(OpenSSLBlockCipher.AES_128_ECB) + Cipher.getInstance("AES_128/ECB/NoPadding", sunJCE)) }; for (BlockCipher cipher : ciphers) @@ -134,8 +132,7 @@ else if ("-nio-block-cipher".equalsIgnoreCase(arg)) Mac[] macs = { new HMac(new SHA1Digest()), - new HMac(new OpenSSLDigest(OpenSSLDigest.SHA1)), - new OpenSSLHMAC(OpenSSLDigest.SHA1) + new OpenSSLHMAC(OpenSSLHMAC.SHA1) }; Random random = new Random(System.currentTimeMillis()); diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/HMACSHA1.java b/src/org/jitsi/impl/neomedia/transform/srtp/HMACSHA1.java index 9ad513aaa..540415a47 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/HMACSHA1.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/HMACSHA1.java @@ -16,8 +16,8 @@ package org.jitsi.impl.neomedia.transform.srtp; import org.bouncycastle.crypto.*; +import org.bouncycastle.crypto.digests.*; import org.bouncycastle.crypto.macs.*; -import org.jitsi.util.*; /** * Implements a factory for an HMAC-SHA1 org.bouncycastle.crypto.Mac. @@ -26,21 +26,6 @@ */ public class HMACSHA1 { - /** - * The Logger used by the HMACSHA1 class to print out - * debug information. - */ - private static final Logger logger = Logger.getLogger(HMACSHA1.class); - - /** - * The indicator which determines whether the OpenSSL (Crypto) library is to - * be used. If true, an attempt will be made to initialize an - * OpenSSLHMAC instance. If the attempt fails, false will - * be assigned in order to not repeatedly attempt the initialization which - * is known to have failed. - */ - private static boolean useOpenSSL = true; - /** * Initializes a new org.bouncycastle.crypto.Mac instance which * implements a keyed-hash message authentication code (HMAC) with SHA-1. @@ -50,38 +35,14 @@ public class HMACSHA1 */ public static Mac createMac() { - // Optionally, use OpenSSL (Crypto). - if (useOpenSSL) + if (OpenSSLWrapperLoader.isLoaded()) { - try - { - return new OpenSSLHMAC(OpenSSLDigest.SHA1); - } - catch (Throwable t) - { - // If an exception is thrown once, it is very likely to be - // thrown multiple times. - useOpenSSL = false; - - if (t instanceof InterruptedException) - { - Thread.currentThread().interrupt(); - } - else if (t instanceof ThreadDeath) - { - throw (ThreadDeath) t; - } - else - { - logger.warn( - "Failed to employ OpenSSL (Crypto) for an optimized" - + " HMAC-SHA1 implementation: " - + t.getLocalizedMessage()); - } - } + return new OpenSSLHMAC(OpenSSLHMAC.SHA1); + } + else + { + // Fallback to BouncyCastle. + return new HMac(new SHA1Digest()); } - - // Fallback to BouncyCastle. - return new HMac(SHA1.createDigest()); } } diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/NIOBlockCipher.java b/src/org/jitsi/impl/neomedia/transform/srtp/NIOBlockCipher.java deleted file mode 100644 index cc42db82a..000000000 --- a/src/org/jitsi/impl/neomedia/transform/srtp/NIOBlockCipher.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jitsi.impl.neomedia.transform.srtp; - -import java.nio.*; - -import org.bouncycastle.crypto.*; - -/** - * Extends org.bouncycastle.crypto.BlockCipher with a - * processBlock method which reads from and writes into - * java.nio.ByteBuffers. - * - * @author Lyubomir Marinov - */ -public interface NIOBlockCipher - extends BlockCipher -{ - /** - * Processes one block of input from the ByteBuffer in and - * writes it to the ByteBuffer out. - * - * @param in the ByteBuffer containing the input data - * @param inOff offset into the ByteBuffer in the data - * starts at - * @param out the ByteBuffer the output data will be copied into - * @param outOff the offset into the ByteBuffer out the output - * will start at - * @exception DataLengthException if there isn't enough data in in, - * or space in out - * @exception IllegalStateException if the cipher isn't initialized - * @return the number of bytes processed and produced - */ - public int processBlock( - ByteBuffer in, int inOff, - ByteBuffer out, int outOff) - throws DataLengthException, IllegalStateException; -} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLBlockCipher.java b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLBlockCipher.java deleted file mode 100644 index f214bf56c..000000000 --- a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLBlockCipher.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jitsi.impl.neomedia.transform.srtp; - -import java.nio.*; - -import org.bouncycastle.crypto.*; -import org.bouncycastle.crypto.params.*; -import org.jitsi.util.*; - -/** - * Implements the interface org.bouncycastle.crypto.BlockCipher using - * the OpenSSL Crypto library. - * - * @author Lyubomir Marinov - */ -public class OpenSSLBlockCipher - implements NIOBlockCipher -{ - public static final int AES_128_CTR = 1; - - public static final int AES_128_ECB = 2; - - private static long EVP_aes_128_ctr; - - private static long EVP_aes_128_ecb; - - /** - * The indicator which determines whether - * System.loadLibrary(String) is to be invoked in order to load the - * OpenSSL (Crypto) library. - */ - private static boolean loadLibrary = true; - - private static native long EVP_aes_128_ecb(); - - private static native int EVP_CIPHER_block_size(long e); - - private static native boolean EVP_CIPHER_CTX_cleanup(long a); - - private static native long EVP_CIPHER_CTX_create(); - - private static native void EVP_CIPHER_CTX_destroy(long ctx); - - private static native boolean EVP_CIPHER_CTX_set_padding( - long x, - boolean padding); - - private static native int EVP_CipherFinal_ex( - long ctx, - byte[] out, int outOff, int outl); - - private static native boolean EVP_CipherInit_ex( - long ctx, - long type, - long impl, - byte[] key, - byte[] iv, - int enc); - - private static native int EVP_CipherUpdate( - long ctx, - byte[] out, int outOff, int outl, - byte[] in, int inOff, int inl); - - private static native int EVP_CipherUpdate( - long ctx, - ByteBuffer out, int outOff, int outl, - ByteBuffer in, int inOff, int inl); - - private static native long EVP_get_cipherbyname(String name); - - /** - * The name of the algorithm implemented by this instance. - */ - private final String algorithmName; - - /** - * The block size in bytes of the cipher implemented by this instance. - */ - private final int blockSize; - - /** - * The cipher context of the OpenSSL (Crypto) library through which the - * actual algorithm implementation is invoked by this instance. - */ - private long ctx; - - /** - * The value of the forEncryption argument in the last invocation - * of {@link #init(boolean, CipherParameters)}. If null, then the - * method init has not been invoked yet. - */ - private Boolean forEncryption; - - /** - * The key provided in the form of a {@link KeyParameter} in the last - * invocation of {@link #init(boolean, CipherParameters)}. - */ - private byte[] key; - - /** - * The OpenSSL Crypto type of the cipher implemented by this instance. - */ - private final long type; - - /** - * Initializes a new OpenSSLBlockCipher instance with a specific - * algorithm. - * - * @param algorithm the algorithm with which to initialize the new instance - * @see #AES_128_CTR - * @see #AES_128_ECB - */ - public OpenSSLBlockCipher(int algorithm) - { - // Make sure the provided arguments are legal. - switch (algorithm) - { - case AES_128_CTR: - case AES_128_ECB: - this.algorithmName = "AES"; - break; - default: - throw new IllegalArgumentException("algorithm " + algorithm); - } - - // Load the OpenSSL (Crypto) library if necessary. - synchronized (OpenSSLBlockCipher.class) - { - if (loadLibrary) - { - try - { - JNIUtils.loadLibrary( - "jnopenssl", - OpenSSLBlockCipher.class.getClassLoader()); - EVP_aes_128_ctr = EVP_get_cipherbyname("AES-128-CTR"); - EVP_aes_128_ecb = EVP_aes_128_ecb(); - } - finally - { - loadLibrary = false; - } - } - } - - long type; - - switch (algorithm) - { - case AES_128_CTR: - long EVP_aes_128_ctr = OpenSSLBlockCipher.EVP_aes_128_ctr; - - if (EVP_aes_128_ctr == 0) - throw new IllegalStateException("EVP_aes_128_ctr"); - else - type = EVP_aes_128_ctr; - break; - case AES_128_ECB: - long EVP_aes_128_ecb = OpenSSLBlockCipher.EVP_aes_128_ecb; - - if (EVP_aes_128_ecb == 0) - throw new IllegalStateException("EVP_aes_128_ecb"); - else - type = EVP_aes_128_ecb; - break; - default: - // It must have been checked prior to loading the OpenSSL (Crypto) - // library but the compiler needs it to be convinced that we are not - // attempting to use an uninitialized variable. - throw new IllegalArgumentException("algorithm " + algorithm); - } - this.type = type; - - long ctx = EVP_CIPHER_CTX_create(); - - if (ctx == 0) - { - throw new RuntimeException("EVP_CIPHER_CTX_create"); - } - else - { - boolean ok = false; - - this.ctx = ctx; - try - { - reset(); - - int blockSize = EVP_CIPHER_block_size(type); - - // The AES we need has a block size of 16 and OpenSSL (Crypto) - // claims it has a block size of 1. - if (algorithm == AES_128_CTR && blockSize == 1) - blockSize = 16; - this.blockSize = blockSize; - - ok = true; - } - finally - { - if (!ok) - { - if (this.ctx == ctx) - this.ctx = 0; - EVP_CIPHER_CTX_destroy(ctx); - } - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void finalize() - throws Throwable - { - try - { - // Well, the destroying in the finalizer should exist as a backup - // anyway. There is no way to explicitly invoke the destroying at - // the time of this writing but it is a start. - long ctx = this.ctx; - - if (ctx != 0) - { - this.ctx = 0; - EVP_CIPHER_CTX_destroy(ctx); - } - } - finally - { - super.finalize(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String getAlgorithmName() - { - return algorithmName; - } - - /** - * {@inheritDoc} - */ - @Override - public int getBlockSize() - { - return blockSize; - } - - /** - * {@inheritDoc} - */ - @Override - public void init(boolean forEncryption, CipherParameters params) - throws IllegalArgumentException - { - byte[] key - = (params instanceof KeyParameter) - ? ((KeyParameter) params).getKey() - : null; - - this.forEncryption = Boolean.valueOf(forEncryption); - this.key = key; - - reset(); - } - - /** - * {@inheritDoc} - */ - @Override - public int processBlock(byte[] in, int inOff, byte[] out, int outOff) - throws DataLengthException, IllegalStateException - { - long ctx = this.ctx; - - if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else - { - int blockSize = getBlockSize(); - int i - = EVP_CipherUpdate( - ctx, - out, outOff, blockSize, - in, inOff, blockSize); - - if (i < 0) - throw new RuntimeException("EVP_CipherUpdate"); - else - return i; - } - } - - /** - * {@inheritDoc} - */ - @Override - public int processBlock( - ByteBuffer in, int inOff, - ByteBuffer out, int outOff) - throws DataLengthException, IllegalStateException - { - long ctx = this.ctx; - - if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else - { - int blockSize = getBlockSize(); - int i - = EVP_CipherUpdate( - ctx, - out, outOff, blockSize, - in, inOff, blockSize); - - if (i < 0) - throw new RuntimeException("EVP_CipherUpdate"); - else - return i; - } - } - - /** - * {@inheritDoc} - */ - @Override - public void reset() - { - long ctx = this.ctx; - - if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else - { - EVP_CIPHER_CTX_cleanup(ctx); - - // As the javadoc on the interface declaration of the method reset - // defines. resetting this cipher leaves it in the same state as it - // was after the last init (if there was one). - Boolean forEncryption = this.forEncryption; - - if (EVP_CipherInit_ex( - ctx, - type, - /* impl */ 0L, - key, - /* iv */ null, - (forEncryption == null) - ? -1 - : (forEncryption.booleanValue() ? 1 : 0))) - { - // The manual page of EVP_CIPHER_CTX_set_padding documents it to - // always return 1 i.e. true. - EVP_CIPHER_CTX_set_padding(ctx, false); - } - else - { - throw new RuntimeException( - "EVP_CipherInit_ex(" + getAlgorithmName() + ")"); - } - } - } -} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLDigest.java b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLDigest.java deleted file mode 100644 index b04762912..000000000 --- a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLDigest.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jitsi.impl.neomedia.transform.srtp; - -import org.bouncycastle.crypto.*; -import org.jitsi.util.*; - -/** - * Implements the interface org.bouncycastle.crypto.Digest using the - * OpenSSL Crypto library. - * - * @author Lyubomir Marinov - */ -public class OpenSSLDigest - implements ExtendedDigest -{ - private static long EVP_sha1; - - /** - * The indicator which determines whether - * System.loadLibrary(String) is to be invoked in order to load the - * OpenSSL (Crypto) library. - */ - private static boolean loadLibrary = true; - - /** - * The algorithm of the SHA-1 cryptographic hash function/digest. - */ - public static final int SHA1 = 1; - - private static native int EVP_DigestFinal_ex( - long ctx, - byte[] md, int off); - - private static native boolean EVP_DigestInit_ex( - long ctx, - long type, - long impl); - - private static native boolean EVP_DigestUpdate( - long ctx, - byte[] d, int off, int cnt); - - private static native int EVP_MD_CTX_block_size(long ctx); - - private static native long EVP_MD_CTX_create(); - - private static native void EVP_MD_CTX_destroy(long ctx); - - private static native int EVP_MD_CTX_size(long ctx); - - private static native long EVP_sha1(); - - /** - * The name of the algorithm implemented by this instance. - */ - private final String algorithmName; - - /** - * The size in bytes of the internal buffer the digest applies its - * compression function to. - */ - private final int byteLength; - - /** - * The digest context of the OpenSSL (Crypto) library through which the - * actual algorithm implementation is invoked by this instance. - */ - private long ctx; - - /** - * The size in bytes of the digest produced by this message digest. - */ - private final int digestSize; - - /** - * The OpenSSL Crypto type of the message digest implemented by this - * instance. - */ - private final long type; - - /** - * Initializes a new OpenSSLDigest instance with a specific - * algorithm. - * - * @param algorithm the algorithm with which to initialize the new instance - * @see #SHA1 - */ - public OpenSSLDigest(int algorithm) - { - // Make sure the provided arguments are legal. - if (algorithm == SHA1) - algorithmName = "SHA-1"; - else - throw new IllegalArgumentException("algorithm " + algorithm); - - // Load the OpenSSL (Crypto) library if necessary. - synchronized (OpenSSLDigest.class) - { - if (loadLibrary) - { - try - { - JNIUtils.loadLibrary( - "jnopenssl", - OpenSSLDigest.class.getClassLoader()); - EVP_sha1 = EVP_sha1(); - } - finally - { - loadLibrary = false; - } - } - } - - long type; - - if (algorithm == SHA1) - { - long EVP_sha1 = OpenSSLDigest.EVP_sha1; - - if (EVP_sha1 == 0) - throw new IllegalStateException("EVP_sha1"); - else - type = EVP_sha1; - } - else - { - // It must have been checked prior to loading the OpenSSL (Crypto) - // library but the compiler needs it to be convinced that we are not - // attempting to use an uninitialized variable. - throw new IllegalArgumentException("algorithm " + algorithm); - } - this.type = type; - - long ctx = EVP_MD_CTX_create(); - - if (ctx == 0) - { - throw new RuntimeException("EVP_MD_CTX_create"); - } - else - { - boolean ok = false; - - this.ctx = ctx; - try - { - reset(); - - // The byteLength and digestSize are actually properties of the - // (OpenSSL Crypto) type so it is really safe to query them - // once in light of the fact that the type is final. - byteLength = EVP_MD_CTX_block_size(ctx); - digestSize = EVP_MD_CTX_size(ctx); - - ok = true; - } - finally - { - if (!ok) - { - if (this.ctx == ctx) - this.ctx = 0; - EVP_MD_CTX_destroy(ctx); - } - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public int doFinal(byte[] out, int off) - { - if (out == null) - throw new NullPointerException("out"); - if ((off < 0) || (out.length <= off)) - throw new ArrayIndexOutOfBoundsException(off); - - long ctx = this.ctx; - - if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else - { - int s = EVP_DigestFinal_ex(ctx, out, off); - - if (s < 0) - { - throw new RuntimeException("EVP_DigestFinal_ex"); - } - else - { - // As the javadoc on interface method specifies, the doFinal - // call leaves this Digest reset. - reset(); - return s; - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void finalize() - throws Throwable - { - try - { - // Well, the destroying in the finalizer should exist as a backup - // anyway. There is no way to explicitly invoke the destroying at - // the time of this writing but it is a start. - long ctx = this.ctx; - - if (ctx != 0) - { - this.ctx = 0; - EVP_MD_CTX_destroy(ctx); - } - } - finally - { - super.finalize(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String getAlgorithmName() - { - return algorithmName; - } - - /** - * {@inheritDoc} - */ - @Override - public int getByteLength() - { - return byteLength; - } - - /** - * {@inheritDoc} - */ - @Override - public int getDigestSize() - { - return digestSize; - } - - /** - * {@inheritDoc} - */ - @Override - public void reset() - { - long ctx = this.ctx; - - if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else if (!EVP_DigestInit_ex(ctx, type, /* impl */ 0L)) - { - throw new RuntimeException( - "EVP_DigestInit_ex(" + getAlgorithmName() + ")"); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void update(byte in) - { - // TODO Auto-generated method stub - } - - /** - * {@inheritDoc} - */ - @Override - public void update(byte[] in, int off, int len) - { - if (len != 0) - { - if (in == null) - throw new NullPointerException("in"); - if ((off < 0) || (in.length <= off)) - throw new ArrayIndexOutOfBoundsException(off); - if ((len < 0) || (in.length < off + len)) - throw new IllegalArgumentException("len " + len); - - long ctx = this.ctx; - - if (ctx == 0) - throw new IllegalStateException("ctx"); - else if (!EVP_DigestUpdate(ctx, in, off, len)) - throw new RuntimeException("EVP_DigestUpdate"); - } - } -} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLHMAC.java b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLHMAC.java index 6e6b0df3d..77bd4a679 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLHMAC.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLHMAC.java @@ -17,7 +17,6 @@ import org.bouncycastle.crypto.*; import org.bouncycastle.crypto.params.*; -import org.jitsi.util.*; /** * Implements the interface org.bouncycastle.crypto.Mac using the @@ -28,21 +27,10 @@ public class OpenSSLHMAC implements Mac { - private static long EVP_sha1; - - /** - * The indicator which determines whether - * System.loadLibrary(String) is to be invoked in order to load the - * OpenSSL (Crypto) library. - */ - private static boolean loadLibrary = true; - private static native int EVP_MD_size(long md); private static native long EVP_sha1(); - private static native void HMAC_CTX_cleanup(long ctx); - private static native long HMAC_CTX_create(); private static native void HMAC_CTX_destroy(long ctx); @@ -64,7 +52,7 @@ private static native boolean HMAC_Update( /** * The name of the algorithm implemented by this instance. */ - private final String algorithmName; + private static final String algorithmName = "SHA-1/HMAC"; /** * The context of the OpenSSL (Crypto) library through which the actual @@ -89,95 +77,39 @@ private static native boolean HMAC_Update( */ private final long md; + /** + * The algorithm of the SHA-1 cryptographic hash function/digest. + */ + public static final int SHA1 = 1; + /** * Initializes a new OpenSSLHMAC instance with a specific digest * algorithm. * * @param digestAlgorithm the algorithm of the digest to initialize the new * instance with - * @see OpenSSLDigest#SHA1 + * @see OpenSSLHMAC#SHA1 */ public OpenSSLHMAC(int digestAlgorithm) { - if (digestAlgorithm == OpenSSLDigest.SHA1) - { - algorithmName = "SHA-1/HMAC"; - } - else - { - throw new IllegalArgumentException( - "digestAlgorithm " + digestAlgorithm); - } - - // Load the OpenSSL (Crypto) library if necessary. - synchronized (OpenSSLDigest.class) - { - if (loadLibrary) - { - try - { - JNIUtils.loadLibrary( - "jnopenssl", - OpenSSLHMAC.class.getClassLoader()); - EVP_sha1 = EVP_sha1(); - } - finally - { - loadLibrary = false; - } - } - } - - long md; + if (!OpenSSLWrapperLoader.isLoaded()) + throw new RuntimeException("OpenSSL wrapper not loaded"); - if (digestAlgorithm == OpenSSLDigest.SHA1) - { - long EVP_sha1 = OpenSSLHMAC.EVP_sha1; - - if (EVP_sha1 == 0) - throw new IllegalStateException("EVP_sha1"); - else - md = EVP_sha1; - } - else - { - // It must have been checked prior to loading the OpenSSL (Crypto) - // library but the compiler needs it to be convinced that we are not - // attempting to use an uninitialized variable. + if (digestAlgorithm != OpenSSLHMAC.SHA1) throw new IllegalArgumentException( "digestAlgorithm " + digestAlgorithm); - } - this.md = md; - - long ctx = HMAC_CTX_create(); - - if (ctx == 0) - { - throw new RuntimeException("HMAC_CTX_create"); - } - else - { - boolean ok = false; - this.ctx = ctx; - try - { - reset(); + md = EVP_sha1(); + if (md == 0) + throw new IllegalStateException("EVP_sha1 == 0"); - macSize = EVP_MD_size(md); + macSize = EVP_MD_size(md); + if (macSize == 0) + throw new IllegalStateException("EVP_MD_size == 0"); - ok = true; - } - finally - { - if (!ok) - { - if (this.ctx == ctx) - this.ctx = 0; - HMAC_CTX_destroy(ctx); - } - } - } + ctx = HMAC_CTX_create(); + if (ctx == 0) + throw new RuntimeException("HMAC_CTX_create == 0"); } /** @@ -276,14 +208,17 @@ public int getMacSize() public void init(CipherParameters params) throws IllegalArgumentException { - byte[] key - = (params instanceof KeyParameter) + key = (params instanceof KeyParameter) ? ((KeyParameter) params).getKey() : null; - this.key = key; + if (key == null) + throw new IllegalStateException("key == null"); + if (ctx == 0) + throw new IllegalStateException("ctx == 0"); - reset(); + if (!HMAC_Init_ex(ctx, key, key.length, md, 0)) + throw new RuntimeException("HMAC_Init_ex() init failed"); } /** @@ -292,29 +227,14 @@ public void init(CipherParameters params) @Override public void reset() { - long ctx = this.ctx; - + if (key == null) + throw new IllegalStateException("key == null"); if (ctx == 0) - { - throw new IllegalStateException("ctx"); - } - else - { - HMAC_CTX_cleanup(ctx); - - // As the javadoc on the interface declaration of the method reset - // defines. resetting this cipher leaves it in the same state as it - // was after the last init (if there was one). - if (!HMAC_Init_ex( - ctx, - key, (key == null) ? 0 : key.length, - md, - /* impl */ 0)) - { - throw new RuntimeException( - "HMAC_Init_ex(" + getAlgorithmName() + ")"); - } - } + throw new IllegalStateException("ctx == 0"); + + // just reset the ctx (keep same key and md) + if (!HMAC_Init_ex(ctx, null, 0, 0, 0)) + throw new RuntimeException("HMAC_Init_ex() reset failed"); } /** diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLWrapperLoader.java b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLWrapperLoader.java new file mode 100644 index 000000000..24d57929c --- /dev/null +++ b/src/org/jitsi/impl/neomedia/transform/srtp/OpenSSLWrapperLoader.java @@ -0,0 +1,65 @@ +/* + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.jitsi.impl.neomedia.transform.srtp; + +import org.jitsi.util.*; + +public class OpenSSLWrapperLoader +{ + /** + * The Logger used by the OpenSSLWrapperLoader class to + * print out debug information. + */ + private static final Logger logger = + Logger.getLogger(OpenSSLWrapperLoader.class); + + /** + * The indicator which determines whether OpenSSL (Crypto) library wrapper + * was loaded. + */ + private static boolean libraryLoaded = false; + + private static native boolean OpenSSL_Init(); + + static + { + try + { + JNIUtils.loadLibrary("jnopenssl", + OpenSSLWrapperLoader.class.getClassLoader()); + if (OpenSSL_Init()) + { + logger.info("jnopenssl successfully loaded"); + libraryLoaded = true; + } + else + { + logger.warn("OpenSSL_Init failed"); + } + } + catch (Throwable t) + { + logger.warn("Unable to load jnopenssl: " + t.toString()); + } + } + + private OpenSSLWrapperLoader() {} + + public static boolean isLoaded() + { + return libraryLoaded; + } +} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SHA1.java b/src/org/jitsi/impl/neomedia/transform/srtp/SHA1.java deleted file mode 100644 index 66f2a6562..000000000 --- a/src/org/jitsi/impl/neomedia/transform/srtp/SHA1.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jitsi.impl.neomedia.transform.srtp; - -import org.bouncycastle.crypto.*; -import org.bouncycastle.crypto.digests.*; -import org.jitsi.util.*; - -/** - * Implements a factory for a SHA-1 Digest. - * - * @author Lyubomir Marinov - */ -public class SHA1 -{ - /** - * The Logger used by the SHA1 class to print out debug - * information. - */ - private static final Logger logger = Logger.getLogger(SHA1.class); - - /** - * The indicator which determines whether the OpenSSL (Crypto) library is to - * be used. If true, an attempt will be made to initialize an - * OpenSSLDigest instance. If the attempt fails, false - * will be assigned in order to not repeatedly attempt the initialization - * which is known to have failed. - */ - private static boolean useOpenSSL = true; - - /** - * Initializes a new org.bouncycastle.crypto.Digest instance which - * implements the SHA-1 cryptographic hash function/digest. - * - * @return a new org.bouncycastle.crypto.Digest instance which - * implements the SHA-1 cryptographic hash function/digest - */ - public static Digest createDigest() - { - // Optionally, use OpenSSL (Crypto). - if (useOpenSSL) - { - try - { - return new OpenSSLDigest(OpenSSLDigest.SHA1); - } - catch (Throwable t) - { - // If an exception is thrown once, it is very likely to be - // thrown multiple times. - useOpenSSL = false; - - if (t instanceof InterruptedException) - { - Thread.currentThread().interrupt(); - } - else if (t instanceof ThreadDeath) - { - throw (ThreadDeath) t; - } - else - { - logger.warn( - "Failed to employ OpenSSL (Crypto) for an optimized" - + " SHA-1 implementation: " - + t.getLocalizedMessage()); - } - } - } - - // Fallback to BouncyCastle. - return new SHA1Digest(); - } -} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTCPCryptoContext.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTCPCryptoContext.java index 904967c7e..06c3a2142 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/SRTCPCryptoContext.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTCPCryptoContext.java @@ -160,21 +160,17 @@ synchronized public void deriveSrtcpKeys() // compute the session encryption key computeIv((byte) 3); - cipher.init(true, new KeyParameter(masterKey)); + cipherCtr.init(masterKey); Arrays.fill(masterKey, (byte) 0); - cipherCtr.getCipherStream( - cipher, - encKey, policy.getEncKeyLength(), - ivStore); + Arrays.fill(encKey, (byte) 0); + cipherCtr.process(encKey, 0, policy.getEncKeyLength(), ivStore); if (authKey != null) { computeIv((byte) 4); - cipherCtr.getCipherStream( - cipher, - authKey, policy.getAuthKeyLength(), - ivStore); + Arrays.fill(authKey, (byte) 0); + cipherCtr.process(authKey, 0, policy.getAuthKeyLength(), ivStore); switch (policy.getAuthType()) { @@ -197,16 +193,14 @@ synchronized public void deriveSrtcpKeys() // compute the session salt computeIv((byte) 5); - cipherCtr.getCipherStream( - cipher, - saltKey, policy.getSaltKeyLength(), - ivStore); + Arrays.fill(saltKey, (byte) 0); + cipherCtr.process(saltKey, 0, policy.getSaltKeyLength(), ivStore); Arrays.fill(masterSalt, (byte) 0); // As last step: initialize cipher with derived encryption key. if (cipherF8 != null) - SRTPCipherF8.deriveForIV(cipherF8, encKey, saltKey); - cipher.init(true, new KeyParameter(encKey)); + cipherF8.init(encKey, saltKey); + cipherCtr.init(encKey); Arrays.fill(encKey, (byte) 0); } @@ -254,7 +248,6 @@ public void processPacketAESCM(RawPacket pkt, int index) int payloadLength = pkt.getLength() - payloadOffset; cipherCtr.process( - cipher, pkt.getBuffer(), pkt.getOffset() + payloadOffset, payloadLength, ivStore); } @@ -290,11 +283,9 @@ public void processPacketAESF8(RawPacket pkt, int index) int payloadOffset = 8; int payloadLength = pkt.getLength() - (4 + policy.getAuthTagLength()); - SRTPCipherF8.process( - cipher, + cipherF8.process( pkt.getBuffer(), pkt.getOffset() + payloadOffset, payloadLength, - ivStore, - cipherF8); + ivStore); } /** diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTR.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTR.java index e1721890b..78bd1f00e 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTR.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTR.java @@ -1,5 +1,5 @@ /* - * Copyright @ 2015 Atlassian Pty Ltd + * Copyright @ 2016 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,108 +15,57 @@ */ package org.jitsi.impl.neomedia.transform.srtp; -import org.bouncycastle.crypto.*; - /** - * SRTPCipherCTR implements SRTP Counter Mode AES Encryption (AES-CM). - * Counter Mode AES Encryption algorithm is defined in RFC3711, section 4.1.1. - * - * Other than Null Cipher, RFC3711 defined two two encryption algorithms: - * Counter Mode AES Encryption and F8 Mode AES encryption. Both encryption - * algorithms are capable to encrypt / decrypt arbitrary length data, and the - * size of packet data is not required to be a multiple of the AES block - * size (128bit). So, no padding is needed. - * - * Please note: these two encryption algorithms are specially defined by SRTP. - * They are not common AES encryption modes, so you will not be able to find a - * replacement implementation in common cryptographic libraries. + * SRTPCipherCTR implementations implement SRTP Counter Mode Encryption. * - * As defined by RFC3711: Counter Mode Encryption is mandatory.. + * SRTP Counter Mode is standard block cipher counter mode with special key and + * special counter initial value (iv). We only increment last 16 bits of the + * counter, so we can only encrypt 2^16 * BLKLEN of data. * - * mandatory to impl optional default - * ------------------------------------------------------------------------- - * encryption AES-CM, NULL AES-f8 AES-CM - * message integrity HMAC-SHA1 - HMAC-SHA1 - * key derivation (PRF) AES-CM - AES-CM - * - * We use AESCipher to handle basic AES encryption / decryption. - * - * @author Werner Dittmann (Werner.Dittmann@t-online.de) - * @author Bing SU (nova.su@gmail.com) + * SRTP Counter Mode AES Encryption algorithm is defined in RFC3711, section + * 4.1.1. */ -public class SRTPCipherCTR +abstract class SRTPCipherCTR { - private static final int BLKLEN = 16; - private static final int MAX_BUFFER_LENGTH = 10 * 1024; - - private final byte[] cipherInBlock = new byte[BLKLEN]; - private byte[] streamBuf = new byte[1024]; - private final byte[] tmpCipherBlock = new byte[BLKLEN]; - - public SRTPCipherCTR() - { - } + protected static final int BLKLEN = 16; /** - * Computes the cipher stream for AES CM mode. See section 4.1.1 in RFC3711 - * for detailed description. + * (Re)Initialize the cipher with key * - * @param out byte array holding the output cipher stream - * @param length length of the cipher stream to produce, in bytes - * @param iv initialization vector used to generate this cipher stream + * @param key the key. key.length == BLKLEN */ - public void getCipherStream( - BlockCipher aesCipher, - byte[] out, int length, - byte[] iv) - { - System.arraycopy(iv, 0, cipherInBlock, 0, 14); - - int ctr, ctrEnd; - - for (ctr = 0, ctrEnd = length / BLKLEN; ctr < ctrEnd; ctr++) - { - // compute the cipher stream - cipherInBlock[14] = (byte) ((ctr & 0xFF00) >> 8); - cipherInBlock[15] = (byte) (ctr & 0x00FF); + public abstract void init(byte[] key); - aesCipher.processBlock(cipherInBlock, 0, out, ctr * BLKLEN); - } - - // Treat the last bytes: - cipherInBlock[14] = (byte) ((ctr & 0xFF00) >> 8); - cipherInBlock[15] = (byte) ((ctr & 0x00FF)); - - aesCipher.processBlock(cipherInBlock, 0, tmpCipherBlock, 0); - System.arraycopy(tmpCipherBlock, 0, out, ctr * BLKLEN, length % BLKLEN); - } + /** + * Process (encrypt/decrypt) data from offset for len bytes iv can be + * modified by this function but you MUST never reuse an IV so it's ok + * + * @param data byte array to be processed + * @param off the offset + * @param len the length + * @param iv initial value of the counter (can be modified). + * iv.length == BLKLEN + */ + public abstract void process(byte[] data, int off, int len, byte[] iv); - public void process( - BlockCipher cipher, - byte[] data, int off, int len, - byte[] iv) + /** + * Check the validity of process function arguments + */ + protected static void checkProcessArgs(byte[] data, int off, int len, byte[] iv) { + if (iv.length != BLKLEN) + throw new IllegalArgumentException("iv.length != BLKLEN"); + if (off < 0) + throw new IllegalArgumentException("off < 0"); + if (len < 0) + throw new IllegalArgumentException("len < 0"); if (off + len > data.length) - return; - - // If data fits in inter buffer, use it. Otherwise, allocate bigger - // buffer and store it (up to a defined maximum size) to use it for - // later processing. - byte[] cipherStream; - - if (len > streamBuf.length) - { - cipherStream = new byte[len]; - if (cipherStream.length <= MAX_BUFFER_LENGTH) - streamBuf = cipherStream; - } - else - { - cipherStream = streamBuf; - } - - getCipherStream(cipher, cipherStream, len, iv); - for (int i = 0; i < len; i++) - data[i + off] ^= cipherStream[i]; + throw new IllegalArgumentException("off + len > data.length"); + /* + * we increment only the last 16 bits of the iv, so we can encrypt + * a maximum of 2^16 blocks, ie 1048576 bytes + */ + if (data.length > 1048576) + throw new IllegalArgumentException("data.length > 1048576"); } } diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRJava.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRJava.java new file mode 100644 index 000000000..09979f801 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRJava.java @@ -0,0 +1,92 @@ +/* + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jitsi.impl.neomedia.transform.srtp; + +import org.bouncycastle.crypto.*; +import org.bouncycastle.crypto.params.*; + +/** + * @see SRTPCipherCTR + * SRTPCipherCTR implementation using Java and a BlockCipher. + * + * You can use any BlockCipher with BLKLEN bytes key and + * block size like TwofishEngine instead of AES. + */ +public class SRTPCipherCTRJava extends SRTPCipherCTR +{ + private final byte[] tmpCipherBlock = new byte[BLKLEN]; + private final BlockCipher cipher; + + public SRTPCipherCTRJava(BlockCipher cipher) + { + this.cipher = cipher; + } + + /** + * {@inheritDoc} + */ + public void init(byte[] key) + { + if (key.length != BLKLEN) + throw new IllegalArgumentException("key.length != BLKLEN"); + + cipher.init(true, new KeyParameter(key)); + } + + /** + * {@inheritDoc} + */ + public void process(byte[] data, int off, int len, byte[] iv) + { + checkProcessArgs(data, off, len, iv); + + int l = len, o = off; + while (l >= BLKLEN) + { + cipher.processBlock(iv, 0, tmpCipherBlock, 0); + //incr counter + if(++iv[15] == 0) ++iv[14]; + //unroll XOR loop to force java to optimise it + data[o+0] ^= tmpCipherBlock[0]; + data[o+1] ^= tmpCipherBlock[1]; + data[o+2] ^= tmpCipherBlock[2]; + data[o+3] ^= tmpCipherBlock[3]; + data[o+4] ^= tmpCipherBlock[4]; + data[o+5] ^= tmpCipherBlock[5]; + data[o+6] ^= tmpCipherBlock[6]; + data[o+7] ^= tmpCipherBlock[7]; + data[o+8] ^= tmpCipherBlock[8]; + data[o+9] ^= tmpCipherBlock[9]; + data[o+10] ^= tmpCipherBlock[10]; + data[o+11] ^= tmpCipherBlock[11]; + data[o+12] ^= tmpCipherBlock[12]; + data[o+13] ^= tmpCipherBlock[13]; + data[o+14] ^= tmpCipherBlock[14]; + data[o+15] ^= tmpCipherBlock[15]; + l -= BLKLEN; + o += BLKLEN; + } + + if (l > 0) + { + cipher.processBlock(iv, 0, tmpCipherBlock, 0); + //incr counter + if(++iv[15] == 0) ++iv[14]; + for (int i = 0; i < l; i++) + data[o+i] ^= tmpCipherBlock[i]; + } + } +} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTROpenSSL.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTROpenSSL.java new file mode 100644 index 000000000..3bf3d7367 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTROpenSSL.java @@ -0,0 +1,102 @@ +/* + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jitsi.impl.neomedia.transform.srtp; + +import org.jitsi.util.*; + +/** + * @see SRTPCipherCTR + * SRTPCipherCTR implementation using OpenSSL via JNI. + */ +public class SRTPCipherCTROpenSSL extends SRTPCipherCTR +{ + /** + * The Logger used by the SRTPCipherCTROpenSSL class to + * print out debug information. + */ + private static final Logger logger = + Logger.getLogger(SRTPCipherCTROpenSSL.class); + + private static native long AES128CTR_CTX_create(); + + private static native void AES128CTR_CTX_destroy(long ctx); + + private static native boolean AES128CTR_CTX_init(long ctx, byte[] key); + + private static native boolean AES128CTR_CTX_process(long ctx, byte[] iv, + byte[] inOut, int offset, int len); + + /** + * the OpenSSL AES128CTR context + */ + private long ctx; + + public SRTPCipherCTROpenSSL() + { + if (!OpenSSLWrapperLoader.isLoaded()) + throw new RuntimeException("OpenSSL wrapper not loaded"); + + ctx = AES128CTR_CTX_create(); + if (ctx == 0) + throw new RuntimeException("CIPHER_CTX_create"); + } + + /** + * {@inheritDoc} + */ + public void init(byte[] key) + { + if (key.length != BLKLEN) + throw new IllegalArgumentException("key.length != BLKLEN"); + + if (!AES128CTR_CTX_init(ctx, key)) + throw new RuntimeException("AES128CTR_CTX_init"); + } + + /** + * {@inheritDoc} + */ + @Override + protected void finalize() throws Throwable + { + try + { + // Well, the destroying in the finalizer should exist as a backup + // anyway. There is no way to explicitly invoke the destroying at + // the time of this writing but it is a start. + if (ctx != 0) + { + AES128CTR_CTX_destroy(ctx); + ctx = 0; + } + } + finally + { + super.finalize(); + } + } + + /** + * {@inheritDoc} + */ + public void process(byte[] data, int off, int len, byte[] iv) + { + checkProcessArgs(data, off, len, iv); + + if (!AES128CTR_CTX_process(ctx, iv, data, off, len)) + throw new RuntimeException("AES128CTR_CTX_process"); + } +} diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8.java index 57e00d922..af74d1a9c 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8.java @@ -21,13 +21,13 @@ import org.bouncycastle.crypto.params.*; /** - * SRTPCipherF8 implements SRTP F8 Mode AES Encryption (AES-f8). + * SRTPCipherF8 implements SRTP F8 Mode Encryption for 128 bits block cipher. * F8 Mode AES Encryption algorithm is defined in RFC3711, section 4.1.2. * * Other than Null Cipher, RFC3711 defined two two encryption algorithms: * Counter Mode AES Encryption and F8 Mode AES encryption. Both encryption * algorithms are capable to encrypt / decrypt arbitrary length data, and the - * size of packet data is not required to be a multiple of the AES block + * size of packet data is not required to be a multiple of the cipher block * size (128bit). So, no padding is needed. * * Please note: these two encryption algorithms are specially defined by SRTP. @@ -42,7 +42,6 @@ * message integrity HMAC-SHA1 - HMAC-SHA1 * key derivation (PRF) AES-CM - AES-CM * - * We use AESCipher to handle basic AES encryption / decryption. * * @author Bing SU (nova.su@gmail.com) * @author Werner Dittmann @@ -50,7 +49,7 @@ public class SRTPCipherF8 { /** - * AES block size, just a short name. + * block size, just a short name. */ private final static int BLKLEN = 16; @@ -65,42 +64,68 @@ static class F8Context long J; } - public static void deriveForIV(BlockCipher f8Cipher, byte[] key, byte[] salt) + /** + * Encryption key + * (k_e) + */ + private byte[] encKey; + + /** + * Masked Encryption key (F8 mode specific) + * (k_e XOR (k_s || 0x555..5)) + */ + private byte[] maskedKey; + + /** + * A 128 bits block cipher (AES or TwoFish) + */ + private BlockCipher cipher; + + public SRTPCipherF8(BlockCipher cipher) { - /* - * Get memory for the special key. This is the key to compute the - * derived IV (IV'). - */ - byte[] saltMask = new byte[key.length]; - byte[] maskedKey = new byte[key.length]; + this.cipher = cipher; + } - /* - * First copy the salt into the mask field, then fill with 0x55 to get a - * full key. - */ - System.arraycopy(salt, 0, saltMask, 0, salt.length); - for (int i = salt.length; i < saltMask.length; ++i) - saltMask[i] = 0x55; + /** + * @param k_e encryption key + * @param k_s salt key + */ + public void init(byte[] k_e, byte[] k_s) + { + if (k_e.length != BLKLEN) + throw new IllegalArgumentException("k_e.length != BLKLEN"); + if (k_s.length > k_e.length) + throw new IllegalArgumentException("k_s.length > k_e.length"); - /* - * XOR the original key with the above created mask to get the special - * key. - */ - for (int i = 0; i < key.length; i++) - maskedKey[i] = (byte) (key[i] ^ saltMask[i]); + encKey = Arrays.copyOf(k_e, k_e.length); /* - * Prepare the f8Cipher with the special key to compute IV' + * XOR the original key with the salt||0x55 to get + * the special key maskedKey. */ - KeyParameter encryptionKey = new KeyParameter(maskedKey); - f8Cipher.init(true, encryptionKey); - saltMask = null; - maskedKey = null; + maskedKey = Arrays.copyOf(k_e, k_e.length); + int i = 0; + for (; i < k_s.length; ++i) + maskedKey[i] ^= k_s[i]; + for (; i < maskedKey.length; ++i) + maskedKey[i] ^= 0x55; } - public static void process(BlockCipher cipher, byte[] data, int off, int len, - byte[] iv, BlockCipher f8Cipher) + public void process(byte[] data, int off, int len, byte[] iv) { + if (iv.length != BLKLEN) + throw new IllegalArgumentException("iv.length != BLKLEN"); + if (off < 0) + throw new IllegalArgumentException("off < 0"); + if (len < 0) + throw new IllegalArgumentException("len < 0"); + if (off + len > data.length) + throw new IllegalArgumentException("off + len > data.length"); + /* + * RFC 3711 says we should not encrypt more than 2^32 blocks which is + * way more than java array max size, so no checks needed here + */ + F8Context f8ctx = new F8Context(); /* @@ -109,27 +134,32 @@ public static void process(BlockCipher cipher, byte[] data, int off, int len, f8ctx.ivAccent = new byte[BLKLEN]; /* - * Use the derived IV encryption setup to encrypt the original IV to produce IV'. + * Encrypt the original IV to produce IV'. + */ + cipher.init(true, new KeyParameter(maskedKey)); + cipher.processBlock(iv, 0, f8ctx.ivAccent, 0); + + /* + * re-init cipher with the "normal" key */ - f8Cipher.processBlock(iv, 0, f8ctx.ivAccent, 0); + cipher.init(true, new KeyParameter(encKey)); f8ctx.J = 0; // initialize the counter f8ctx.S = new byte[BLKLEN]; // get the key stream buffer - Arrays.fill(f8ctx.S, (byte) 0); int inLen = len; while (inLen >= BLKLEN) { - processBlock(cipher, f8ctx, data, off, data, off, BLKLEN); + processBlock(f8ctx, data, off, BLKLEN); inLen -= BLKLEN; off += BLKLEN; } if (inLen > 0) { - processBlock(cipher, f8ctx, data, off, data, off, inLen); + processBlock(f8ctx, data, off, inLen); } } @@ -139,19 +169,14 @@ public static void process(BlockCipher cipher, byte[] data, int off, int len, * * @param f8ctx * F8 encryption context - * @param in + * @param inOut * byte array holding the data to be processed - * @param inOff - * start offset of the data to be processed inside in array - * @param out - * byte array that will hold the processed data - * @param outOff - * start offset of output data in out + * @param off + * start offset of the data to be processed inside inOut array * @param len - * length of the input data + * length of the data to be processed inside inOut array from off */ - private static void processBlock(BlockCipher cipher, F8Context f8ctx, - byte[] in, int inOff, byte[] out, int outOff, int len) + private void processBlock(F8Context f8ctx, byte[] inOut, int off, int len) { /* * XOR the previous key stream with IV' @@ -180,6 +205,6 @@ private static void processBlock(BlockCipher cipher, F8Context f8ctx, * the cipher text. */ for (int i = 0; i < len; i++) - out[outOff + i] = (byte) (in[inOff + i] ^ f8ctx.S[i]); + inOut[off + i] ^= f8ctx.S[i]; } } diff --git a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCryptoContext.java b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCryptoContext.java index 7f6e6f90f..c265bab5d 100644 --- a/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCryptoContext.java +++ b/src/org/jitsi/impl/neomedia/transform/srtp/SRTPCryptoContext.java @@ -395,22 +395,18 @@ synchronized public void deriveSrtpKeys(long index) // compute the session encryption key computeIv(0x00, index); - cipher.init(true, new KeyParameter(masterKey)); + cipherCtr.init(masterKey); Arrays.fill(masterKey, (byte) 0); - cipherCtr.getCipherStream( - cipher, - encKey, policy.getEncKeyLength(), - ivStore); + Arrays.fill(encKey, (byte) 0); + cipherCtr.process(encKey, 0, policy.getEncKeyLength(), ivStore); // compute the session authentication key if (authKey != null) { computeIv(0x01, index); - cipherCtr.getCipherStream( - cipher, - authKey, policy.getAuthKeyLength(), - ivStore); + Arrays.fill(authKey, (byte) 0); + cipherCtr.process(authKey, 0, policy.getAuthKeyLength(), ivStore); switch (policy.getAuthType()) { @@ -433,16 +429,14 @@ synchronized public void deriveSrtpKeys(long index) // compute the session salt computeIv(0x02, index); - cipherCtr.getCipherStream( - cipher, - saltKey, policy.getSaltKeyLength(), - ivStore); + Arrays.fill(saltKey, (byte) 0); + cipherCtr.process(saltKey, 0, policy.getSaltKeyLength(), ivStore); Arrays.fill(masterSalt, (byte) 0); // As last step: initialize cipher with derived encryption key. if (cipherF8 != null) - SRTPCipherF8.deriveForIV(cipherF8, encKey, saltKey); - cipher.init(true, new KeyParameter(encKey)); + cipherF8.init(encKey, saltKey); + cipherCtr.init(encKey); Arrays.fill(encKey, (byte) 0); } @@ -519,7 +513,6 @@ public void processPacketAESCM(RawPacket pkt) int payloadLength = pkt.getPayloadLength(); cipherCtr.process( - cipher, pkt.getBuffer(), pkt.getOffset() + payloadOffset, payloadLength, ivStore); } @@ -547,11 +540,9 @@ public void processPacketAESF8(RawPacket pkt) int payloadOffset = pkt.getHeaderLength(); int payloadLength = pkt.getPayloadLength(); - SRTPCipherF8.process( - cipher, + cipherF8.process( pkt.getBuffer(), pkt.getOffset() + payloadOffset, payloadLength, - ivStore, - cipherF8); + ivStore); } /** diff --git a/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRTest.java b/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRTest.java new file mode 100644 index 000000000..2d5945e33 --- /dev/null +++ b/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherCTRTest.java @@ -0,0 +1,66 @@ +package org.jitsi.impl.neomedia.transform.srtp; + +import static org.junit.Assert.*; +import java.util.Arrays; +import javax.xml.bind.DatatypeConverter; +import org.bouncycastle.crypto.engines.AESFastEngine; +import org.junit.Test; + +public class SRTPCipherCTRTest +{ + // RFC 3711 AES CTR Tests vectors + public static final byte[] TV_Key = + DatatypeConverter.parseHexBinary("2B7E151628AED2A6ABF7158809CF4F3C"); + + public static final byte[] TV_IV_1 = + DatatypeConverter.parseHexBinary("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0000"); + + public static final byte[] TV_Cipher_AES_1 = + DatatypeConverter.parseHexBinary("E03EAD0935C95E80E166B16DD92B4EB4" + + "D23513162B02D0F72A43A2FE4A5F97AB" + + "41E95B3BB0A2E8DD477901E4FCA894C0"); + + public static final byte[] TV_IV_2 = + DatatypeConverter.parseHexBinary("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"); + + public static final byte[] TV_Cipher_AES_2 = + DatatypeConverter.parseHexBinary("EC8CDF7398607CB0F2D21675EA9EA1E4" + + "362B7C3C6773516318A077D7FC5073AE" + + "6A2CC3787889374FBEB4C81B17BA6C44"); + + @Test + public void testJavaCTRAES() + { + SRTPCipherCTR cipher = new SRTPCipherCTRJava(new AESFastEngine()); + cipher.init(TV_Key); + byte[] data = new byte[TV_Cipher_AES_1.length]; + + Arrays.fill(data, (byte) 0); + byte[] iv = Arrays.copyOf(TV_IV_1, TV_IV_1.length); + cipher.process(data, 0, data.length, iv); + assertArrayEquals(data, TV_Cipher_AES_1); + + Arrays.fill(data, (byte) 0); + iv = Arrays.copyOf(TV_IV_2, TV_IV_2.length); + cipher.process(data, 0, data.length, iv); + assertArrayEquals(data, TV_Cipher_AES_2); + } + + @Test + public void testOpenSSLCTRAES() + { + SRTPCipherCTR cipher = new SRTPCipherCTROpenSSL(); + cipher.init(TV_Key); + byte[] data = new byte[TV_Cipher_AES_1.length]; + + Arrays.fill(data, (byte) 0); + byte[] iv = Arrays.copyOf(TV_IV_1, TV_IV_1.length); + cipher.process(data, 0, data.length, iv); + assertArrayEquals(data, TV_Cipher_AES_1); + + Arrays.fill(data, (byte) 0); + iv = Arrays.copyOf(TV_IV_2, TV_IV_2.length); + cipher.process(data, 0, data.length, iv); + assertArrayEquals(data, TV_Cipher_AES_2); + } +} diff --git a/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8Test.java b/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8Test.java new file mode 100644 index 000000000..4e1ec483f --- /dev/null +++ b/test/org/jitsi/impl/neomedia/transform/srtp/SRTPCipherF8Test.java @@ -0,0 +1,68 @@ +package org.jitsi.impl.neomedia.transform.srtp; + +import static org.junit.Assert.*; +import java.util.Arrays; +import javax.xml.bind.DatatypeConverter; +import org.bouncycastle.crypto.engines.*; +import org.junit.*; + +public class SRTPCipherF8Test +{ + // RFC 3711 AES F8 Tests vectors + public static final byte[] TV_Key = + DatatypeConverter.parseHexBinary("234829008467be186c3de14aae72d62c"); + + public static final byte[] TV_Salt = + DatatypeConverter.parseHexBinary("32f2870d"); + + public static final byte[] TV_IV = + DatatypeConverter.parseHexBinary("006e5cba50681de55c621599d462564a"); + + public static final byte[] TV_Plain = + DatatypeConverter.parseHexBinary("70736575646f72616e646f6d6e657373" + + "20697320746865206e65787420626573" + "74207468696e67"); + + public static final byte[] TV_Cipher_AES = + DatatypeConverter.parseHexBinary("019ce7a26e7854014a6366aa95d4eefd" + + "1ad4172a14f9faf455b7f1d4b62bd08f" + "562c0eef7c4802"); + + // Generated with our own implementation + public static final byte[] TV_Cipher_TwoFish = + DatatypeConverter.parseHexBinary("346d91e0d4c3908c476ba25f2792fbb6" + + "5456f2d90736f40353da7865a8989f01" + "947f6f09385fb5"); + + /** + * Validate our F8 mode implementation with tests vectors provided in + * RFC3711 + * + * @throws Exception + */ + @Test + public void testAES() throws Exception + { + SRTPCipherF8 cipher = new SRTPCipherF8(new AESFastEngine()); + cipher.init(TV_Key, TV_Salt); + byte[] data = Arrays.copyOf(TV_Plain, TV_Plain.length); + byte[] iv = Arrays.copyOf(TV_IV, TV_IV.length); + cipher.process(data, 0, data.length, iv); + + assertArrayEquals(data, TV_Cipher_AES); + } + + /** + * Validate our F8 mode implementation work with TwoFish + * + * @throws Exception + */ + @Test + public void testTwoFish() throws Exception + { + SRTPCipherF8 cipher = new SRTPCipherF8(new TwofishEngine()); + cipher.init(TV_Key, TV_Salt); + byte[] data = Arrays.copyOf(TV_Plain, TV_Plain.length); + byte[] iv = Arrays.copyOf(TV_IV, TV_IV.length); + cipher.process(data, 0, data.length, iv); + + assertArrayEquals(data, TV_Cipher_TwoFish); + } +}