/** * This file provides a native method to supplement the Fast implementation * of RSA's MD5 hash generator in Java JDK Beta-2 or higher. * This file is Copyright (c) 2002 - 2005 Timothy W Macinta. *

* This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *

* This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. *

* You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *

* See http://www.twmacinta.com/myjava/fast_md5.php for more information * on this package. *

* To compile this file on Linux, the following command may be used, * depending on your system: *

 *      gcc -O3 -shared -I${JAVADIR}include -I${JAVADIR}include/linux com/twmacinta/util/MD5.c -o lib/arch/linux_x86/MD5.so
 * 
* where ${JAVADIR} is the directory where you have installed the JDK. *

* To compile this file on Windows, the following commands may be used, * depending on your system (the following should work with the MinGW * distribution, and perhaps with other distributions as well): *

 *      gcc -O3 -c -I%JAVADIR%include -I%JAVADIR%include/win32 MD5.c
 *      dllwrap --output-def MD5.def --add-stdcall-alias -o MD5.dll -s MD5.o
 * 
* where %JAVADIR% is the directory where you have installed the JDK. *

* To compile this file on Mac OS X, the following command may be used, * depending on your system: *

 *      gcc -O3 -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers -o lib/arch/darwin_ppc/MD5.jnilib -framework JavaVM com/twmacinta/util/MD5.c
 * 
* * @author Timothy W Macinta (twm@alum.mit.edu) */ ////////////////////////////////////////////// // // #include #include #include //#include #include "MD5.h" /** Determine endian-ness. **/ #ifdef __WIN32__ #include #else #ifdef __APPLE__ #include #else //#include #endif #endif #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #ifndef __BYTE_ORDER #define __BYTE_ORDER BYTE_ORDER #endif // // ////////////////////////////////////////////// #define ROTATE_LEFT_UINT32(i, shift_left) (((i) << (shift_left)) | ((i) >> (32 - (shift_left)))) JNIEXPORT void JNICALL Java_com_twmacinta_util_MD5_Transform_1native (JNIEnv *env, jobject obj, jintArray state, jbyteArray buffer, jint shift, jint length) { register uint32_t a; register uint32_t b; register uint32_t c; register uint32_t d; uint32_t a0, b0, c0, d0, i, buffer_index; #if __BYTE_ORDER == __LITTLE_ENDIAN uint32_t *x; #else uint32_t x[16]; #endif jbyte buffer_elem[length]; /* Copy the state to local variables **/ jint *state_elem = (*env)->GetIntArrayElements(env, state, 0); a0 = state_elem[0]; b0 = state_elem[1]; c0 = state_elem[2]; d0 = state_elem[3]; /* Copy the region to be hashed into memory on the stack **/ (*env)->GetByteArrayRegion(env, buffer, shift, length, buffer_elem); /* Loop through the region to be hashed in chunks of 64 bytes **/ buffer_index = 0; for (buffer_index = 0; buffer_index + 63 < length; buffer_index += 64) { /* Save a copy of the state before modifications */ a = a0; b = b0; c = c0; d = d0; /* equivalent to Decode(buffer, shift, decode_buf); in the Java code */ #if __BYTE_ORDER == __LITTLE_ENDIAN x = (uint32_t *) (buffer_elem + buffer_index); #else x[0] = ((int) (buffer_elem[buffer_index] & 0xff)) | (((int) (buffer_elem[buffer_index + 1] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 2] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 3]) << 24); x[1] = ((int) (buffer_elem[buffer_index + 4] & 0xff)) | (((int) (buffer_elem[buffer_index + 5] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 6] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 7]) << 24); x[2] = ((int) (buffer_elem[buffer_index + 8] & 0xff)) | (((int) (buffer_elem[buffer_index + 9] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 10] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 11]) << 24); x[3] = ((int) (buffer_elem[buffer_index + 12] & 0xff)) | (((int) (buffer_elem[buffer_index + 13] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 14] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 15]) << 24); x[4] = ((int) (buffer_elem[buffer_index + 16] & 0xff)) | (((int) (buffer_elem[buffer_index + 17] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 18] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 19]) << 24); x[5] = ((int) (buffer_elem[buffer_index + 20] & 0xff)) | (((int) (buffer_elem[buffer_index + 21] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 22] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 23]) << 24); x[6] = ((int) (buffer_elem[buffer_index + 24] & 0xff)) | (((int) (buffer_elem[buffer_index + 25] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 26] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 27]) << 24); x[7] = ((int) (buffer_elem[buffer_index + 28] & 0xff)) | (((int) (buffer_elem[buffer_index + 29] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 30] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 31]) << 24); x[8] = ((int) (buffer_elem[buffer_index + 32] & 0xff)) | (((int) (buffer_elem[buffer_index + 33] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 34] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 35]) << 24); x[9] = ((int) (buffer_elem[buffer_index + 36] & 0xff)) | (((int) (buffer_elem[buffer_index + 37] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 38] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 39]) << 24); x[10] = ((int) (buffer_elem[buffer_index + 40] & 0xff)) | (((int) (buffer_elem[buffer_index + 41] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 42] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 43]) << 24); x[11] = ((int) (buffer_elem[buffer_index + 44] & 0xff)) | (((int) (buffer_elem[buffer_index + 45] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 46] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 47]) << 24); x[12] = ((int) (buffer_elem[buffer_index + 48] & 0xff)) | (((int) (buffer_elem[buffer_index + 49] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 50] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 51]) << 24); x[13] = ((int) (buffer_elem[buffer_index + 52] & 0xff)) | (((int) (buffer_elem[buffer_index + 53] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 54] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 55]) << 24); x[14] = ((int) (buffer_elem[buffer_index + 56] & 0xff)) | (((int) (buffer_elem[buffer_index + 57] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 58] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 59]) << 24); x[15] = ((int) (buffer_elem[buffer_index + 60] & 0xff)) | (((int) (buffer_elem[buffer_index + 61] & 0xff)) << 8) | (((int) (buffer_elem[buffer_index + 62] & 0xff)) << 16) | (((int) buffer_elem[buffer_index + 63]) << 24); #endif /* Round 1 */ a += ((b & c) | (~b & d)) + x[ 0] + 0xd76aa478; /* 1 */ a = ROTATE_LEFT_UINT32(a, 7) + b; d += ((a & b) | (~a & c)) + x[ 1] + 0xe8c7b756; /* 2 */ d = ROTATE_LEFT_UINT32(d, 12) + a; c += ((d & a) | (~d & b)) + x[ 2] + 0x242070db; /* 3 */ c = ROTATE_LEFT_UINT32(c, 17) + d; b += ((c & d) | (~c & a)) + x[ 3] + 0xc1bdceee; /* 4 */ b = ROTATE_LEFT_UINT32(b, 22) + c; a += ((b & c) | (~b & d)) + x[ 4] + 0xf57c0faf; /* 5 */ a = ROTATE_LEFT_UINT32(a, 7) + b; d += ((a & b) | (~a & c)) + x[ 5] + 0x4787c62a; /* 6 */ d = ROTATE_LEFT_UINT32(d, 12) + a; c += ((d & a) | (~d & b)) + x[ 6] + 0xa8304613; /* 7 */ c = ROTATE_LEFT_UINT32(c, 17) + d; b += ((c & d) | (~c & a)) + x[ 7] + 0xfd469501; /* 8 */ b = ROTATE_LEFT_UINT32(b, 22) + c; a += ((b & c) | (~b & d)) + x[ 8] + 0x698098d8; /* 9 */ a = ROTATE_LEFT_UINT32(a, 7) + b; d += ((a & b) | (~a & c)) + x[ 9] + 0x8b44f7af; /* 10 */ d = ROTATE_LEFT_UINT32(d, 12) + a; c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */ c = ROTATE_LEFT_UINT32(c, 17) + d; b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */ b = ROTATE_LEFT_UINT32(b, 22) + c; a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */ a = ROTATE_LEFT_UINT32(a, 7) + b; d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */ d = ROTATE_LEFT_UINT32(d, 12) + a; c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */ c = ROTATE_LEFT_UINT32(c, 17) + d; b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */ b = ROTATE_LEFT_UINT32(b, 22) + c; /* Round 2 */ a += ((b & d) | (c & ~d)) + x[ 1] + 0xf61e2562; /* 17 */ a = ROTATE_LEFT_UINT32(a, 5) + b; d += ((a & c) | (b & ~c)) + x[ 6] + 0xc040b340; /* 18 */ d = ROTATE_LEFT_UINT32(d, 9) + a; c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */ c = ROTATE_LEFT_UINT32(c, 14) + d; b += ((c & a) | (d & ~a)) + x[ 0] + 0xe9b6c7aa; /* 20 */ b = ROTATE_LEFT_UINT32(b, 20) + c; a += ((b & d) | (c & ~d)) + x[ 5] + 0xd62f105d; /* 21 */ a = ROTATE_LEFT_UINT32(a, 5) + b; d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */ d = ROTATE_LEFT_UINT32(d, 9) + a; c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */ c = ROTATE_LEFT_UINT32(c, 14) + d; b += ((c & a) | (d & ~a)) + x[ 4] + 0xe7d3fbc8; /* 24 */ b = ROTATE_LEFT_UINT32(b, 20) + c; a += ((b & d) | (c & ~d)) + x[ 9] + 0x21e1cde6; /* 25 */ a = ROTATE_LEFT_UINT32(a, 5) + b; d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */ d = ROTATE_LEFT_UINT32(d, 9) + a; c += ((d & b) | (a & ~b)) + x[ 3] + 0xf4d50d87; /* 27 */ c = ROTATE_LEFT_UINT32(c, 14) + d; b += ((c & a) | (d & ~a)) + x[ 8] + 0x455a14ed; /* 28 */ b = ROTATE_LEFT_UINT32(b, 20) + c; a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */ a = ROTATE_LEFT_UINT32(a, 5) + b; d += ((a & c) | (b & ~c)) + x[ 2] + 0xfcefa3f8; /* 30 */ d = ROTATE_LEFT_UINT32(d, 9) + a; c += ((d & b) | (a & ~b)) + x[ 7] + 0x676f02d9; /* 31 */ c = ROTATE_LEFT_UINT32(c, 14) + d; b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */ b = ROTATE_LEFT_UINT32(b, 20) + c; /* Round 3 */ a += (b ^ c ^ d) + x[ 5] + 0xfffa3942; /* 33 */ a = ROTATE_LEFT_UINT32(a, 4) + b; d += (a ^ b ^ c) + x[ 8] + 0x8771f681; /* 34 */ d = ROTATE_LEFT_UINT32(d, 11) + a; c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */ c = ROTATE_LEFT_UINT32(c, 16) + d; b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */ b = ROTATE_LEFT_UINT32(b, 23) + c; a += (b ^ c ^ d) + x[ 1] + 0xa4beea44; /* 37 */ a = ROTATE_LEFT_UINT32(a, 4) + b; d += (a ^ b ^ c) + x[ 4] + 0x4bdecfa9; /* 38 */ d = ROTATE_LEFT_UINT32(d, 11) + a; c += (d ^ a ^ b) + x[ 7] + 0xf6bb4b60; /* 39 */ c = ROTATE_LEFT_UINT32(c, 16) + d; b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */ b = ROTATE_LEFT_UINT32(b, 23) + c; a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */ a = ROTATE_LEFT_UINT32(a, 4) + b; d += (a ^ b ^ c) + x[ 0] + 0xeaa127fa; /* 42 */ d = ROTATE_LEFT_UINT32(d, 11) + a; c += (d ^ a ^ b) + x[ 3] + 0xd4ef3085; /* 43 */ c = ROTATE_LEFT_UINT32(c, 16) + d; b += (c ^ d ^ a) + x[ 6] + 0x04881d05; /* 44 */ b = ROTATE_LEFT_UINT32(b, 23) + c; a += (b ^ c ^ d) + x[ 9] + 0xd9d4d039; /* 33 */ a = ROTATE_LEFT_UINT32(a, 4) + b; d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */ d = ROTATE_LEFT_UINT32(d, 11) + a; c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */ c = ROTATE_LEFT_UINT32(c, 16) + d; b += (c ^ d ^ a) + x[ 2] + 0xc4ac5665; /* 36 */ b = ROTATE_LEFT_UINT32(b, 23) + c; /* Round 4 */ a += (c ^ (b | ~d)) + x[ 0] + 0xf4292244; /* 49 */ a = ROTATE_LEFT_UINT32(a, 6) + b; d += (b ^ (a | ~c)) + x[ 7] + 0x432aff97; /* 50 */ d = ROTATE_LEFT_UINT32(d, 10) + a; c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */ c = ROTATE_LEFT_UINT32(c, 15) + d; b += (d ^ (c | ~a)) + x[ 5] + 0xfc93a039; /* 52 */ b = ROTATE_LEFT_UINT32(b, 21) + c; a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */ a = ROTATE_LEFT_UINT32(a, 6) + b; d += (b ^ (a | ~c)) + x[ 3] + 0x8f0ccc92; /* 54 */ d = ROTATE_LEFT_UINT32(d, 10) + a; c += (a ^ (d | ~b)) + x[10] + 0xffeff47d; /* 55 */ c = ROTATE_LEFT_UINT32(c, 15) + d; b += (d ^ (c | ~a)) + x[ 1] + 0x85845dd1; /* 56 */ b = ROTATE_LEFT_UINT32(b, 21) + c; a += (c ^ (b | ~d)) + x[ 8] + 0x6fa87e4f; /* 57 */ a = ROTATE_LEFT_UINT32(a, 6) + b; d += (b ^ (a | ~c)) + x[15] + 0xfe2ce6e0; /* 58 */ d = ROTATE_LEFT_UINT32(d, 10) + a; c += (a ^ (d | ~b)) + x[ 6] + 0xa3014314; /* 59 */ c = ROTATE_LEFT_UINT32(c, 15) + d; b += (d ^ (c | ~a)) + x[13] + 0x4e0811a1; /* 60 */ b = ROTATE_LEFT_UINT32(b, 21) + c; a += (c ^ (b | ~d)) + x[ 4] + 0xf7537e82; /* 61 */ a = ROTATE_LEFT_UINT32(a, 6) + b; d += (b ^ (a | ~c)) + x[11] + 0xbd3af235; /* 62 */ d = ROTATE_LEFT_UINT32(d, 10) + a; c += (a ^ (d | ~b)) + x[ 2] + 0x2ad7d2bb; /* 63 */ c = ROTATE_LEFT_UINT32(c, 15) + d; b += (d ^ (c | ~a)) + x[ 9] + 0xeb86d391; /* 64 */ b = ROTATE_LEFT_UINT32(b, 21) + c; /* update the state */ a0 += a; b0 += b; c0 += c; d0 += d; } /* update the state array */ state_elem[0] = a0; state_elem[1] = b0; state_elem[2] = c0; state_elem[3] = d0; (*env)->ReleaseIntArrayElements(env, state, state_elem, 0); }