Skip to content
Snippets Groups Projects
Commit 8dd83b67 authored by Lyubomir Marinov's avatar Lyubomir Marinov
Browse files

Prepares to use SHA-1 from OpenSSL instead of BouncyCastle.

parent c07e2f4c
No related branches found
No related tags found
No related merge requests found
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
#include "Digest.h"
#include <openssl/evp.h>
#include <stdint.h>
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, md_ + off, &s);
(*env)->ReleasePrimitiveArrayCritical(env, md, md_, 0);
i = i ? ((int) s) : -1;
}
else
{
i = -1;
}
return i;
}
JNIEXPORT jboolean JNICALL
Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1DigestInit_1ex
(JNIEnv *env, jclass clazz, jlong ctx, jlong type, jlong impl)
{
int i
= EVP_DigestInit_ex(
(EVP_MD_CTX *) (intptr_t) ctx,
(const EVP_MD *) (intptr_t) type,
(ENGINE *) (intptr_t) impl);
return i ? JNI_TRUE : JNI_FALSE;
}
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 b;
if (d_)
{
int i = EVP_DigestUpdate((EVP_MD_CTX *) (intptr_t) ctx, d_ + off, cnt);
(*env)->ReleasePrimitiveArrayCritical(env, d, d_, JNI_ABORT);
b = i ? JNI_TRUE : JNI_FALSE;
}
else
{
b = JNI_FALSE;
}
return b;
}
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);
}
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();
}
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);
}
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);
}
JNIEXPORT jlong JNICALL
Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLDigest_EVP_1sha1
(JNIEnv *env, jclass clazz)
{
return (jlong) (intptr_t) EVP_sha1();
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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
......@@ -109,8 +109,8 @@ else if (t instanceof ThreadDeath)
{
logger.warn(
"Failed to employ a java.security.Provider for an"
+ " optimized AES implementation.",
t);
+ " optimized AES implementation: "
+ t.getLocalizedMessage());
}
}
}
......
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jitsi.impl.neomedia.transform.srtp;
import org.bouncycastle.crypto.*;
/**
* Implements the interface <tt>org.bouncycastle.crypto.Digest</tt> using the
* OpenSSL Crypto library.
*
* @author Lyubomir Marinov
*/
public class OpenSSLDigest
implements ExtendedDigest
{
private static long EVP_sha1;
/**
* The indicator which determines whether
* <tt>System.loadLibrary(String)</tt> 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 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 int digestSize;
/**
* The OpenSSL Crypto type of the message digest implemented by this
* instance.
*/
private final long type;
/**
* Initializes a new <tt>OpenSSLDigest</tt> with a specific algorithm.
*
* @param algorithm the algorithm with which to initialize the new instance
*/
public OpenSSLDigest(int algorithm)
{
// Make sure the provided arguments are legal.
if (algorithm == SHA1)
this.algorithmName = "SHA-1";
else
throw new IllegalArgumentException("algorithm " + algorithm);
// Load the OpenSSL (Crypto) library if necessary.
synchronized (OpenSSLDigest.class)
{
if (loadLibrary)
{
try
{
System.loadLibrary("jnopenssl");
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();
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 */ 0))
{
byteLength = EVP_MD_CTX_block_size(ctx);
digestSize = EVP_MD_CTX_size(ctx);
}
else
{
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");
}
}
}
......@@ -8,12 +8,69 @@
import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.digests.*;
import org.jitsi.util.*;
class SHA1
/**
* Implements a factory for a SHA-1 <tt>Digest</tt>.
*
* @author Lyubomir Marinov
*/
public class SHA1
{
static Digest createDigest()
/**
* The <tt>Logger</tt> used by the <tt>SHA1</tt> 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 <tt>true</tt>, an attempt will be made to initialize an
* <tt>OpenSSLDigest</tt> instance. If the attempt fails, <tt>false</tt>
* 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 <tt>org.bouncycastle.crypto.Digest</tt> instance which
* implements the SHA-1 cryptographic hash function/digest.
*
* @return a new <tt>org.bouncycastle.crypto.Digest</tt> instance which
* implements the SHA-1 cryptographic hash function/digest
*/
public static Digest createDigest()
{
// TODO Auto-generated method stub
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());
}
}
}
return new SHA1Digest();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment