Author: mturk Date: Fri Aug 7 20:45:48 2009 New Revision: 802177 URL: http://svn.apache.org/viewvc?rev=802177&view=rev Log: Port APR's md5 code
Added: commons/sandbox/runtime/trunk/src/main/native/shared/md5.c (with props) Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in commons/sandbox/runtime/trunk/src/main/native/include/acr_crypto.h commons/sandbox/runtime/trunk/src/main/native/shared/sha.c Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=802177&r1=802176&r2=802177&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Fri Aug 7 20:45:48 2009 @@ -87,6 +87,7 @@ $(SRCDIR)/shared/nbb.$(OBJ) \ $(SRCDIR)/shared/pointer.$(OBJ) \ $(SRCDIR)/shared/object.$(OBJ) \ + $(SRCDIR)/shared/md5.$(OBJ) \ $(SRCDIR)/shared/sha.$(OBJ) \ $(SRCDIR)/shared/string.$(OBJ) \ $(SRCDIR)/shared/tables.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in?rev=802177&r1=802176&r2=802177&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Fri Aug 7 20:45:48 2009 @@ -80,6 +80,7 @@ $(SRCDIR)/shared/nbb.$(OBJ) \ $(SRCDIR)/shared/pointer.$(OBJ) \ $(SRCDIR)/shared/object.$(OBJ) \ + $(SRCDIR)/shared/md5.$(OBJ) \ $(SRCDIR)/shared/sha.$(OBJ) \ $(SRCDIR)/shared/string.$(OBJ) \ $(SRCDIR)/shared/tables.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_crypto.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_crypto.h?rev=802177&r1=802176&r2=802177&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_crypto.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_crypto.h Fri Aug 7 20:45:48 2009 @@ -31,29 +31,33 @@ * */ +#define ACR_SHA1_BLOCK_LENGTH 64 +#define ACR_SHA1_DIGEST_LENGTH 20 +#define ACR_SHA1_DIGEST_STRING_LENGTH (ACR_SHA1_DIGEST_LENGTH * 2 + 1) + +#define ACR_MD5_BLOCK_LENGTH 64 +#define ACR_MD5_DIGEST_LENGTH 16 +#define ACR_MD5_DIGEST_STRING_LENGTH (ACR_MD5_DIGEST_LENGTH * 2 + 1) + +typedef struct acr_sha1_ctx_t { + acr_uint32_t state[5]; + acr_uint64_t count; + acr_byte_t buffer[ACR_SHA1_BLOCK_LENGTH]; +} acr_sha1_ctx_t; + +typedef struct acr_md5_ctx_t { + acr_uint32_t state[4]; /* state */ + acr_uint64_t count; /* number of bits, mod 2^64 */ + acr_byte_t buffer[ACR_MD5_BLOCK_LENGTH]; /* input buffer */ +} acr_md5_ctx_t; + + /** * Size of the SHA1 DIGEST */ #define ACR_SHA1_DIGESTSIZE 20 #define ACR_SHA1_BASE16SIZE 41 -/** @see acr_sha1_ctx_t */ -typedef struct acr_sha1_ctx_t acr_sha1_ctx_t; - -/** - * SHA1 context structure - */ -struct acr_sha1_ctx_t { - /** message digest */ - acr_uint32_t digest[5]; - /** 64-bit bit counts */ - acr_uint32_t count_lo, count_hi; - /** SHA data buffer */ - acr_uint32_t data[16]; - /** unprocessed amount in data */ - int local; -}; - /** * Initialize the SHA digest * @param context The SHA context to initialize @@ -68,7 +72,7 @@ */ ACR_DECLARE(void) ACR_Sha1Update(acr_sha1_ctx_t *context, const unsigned char *input, - unsigned int count); + size_t count); /** * Update the SHA digest @@ -78,7 +82,7 @@ */ ACR_DECLARE(void) ACR_Sha1UpdateA(acr_sha1_ctx_t *context, const char *input, - unsigned int count); + size_t count); /** * Update the SHA digest @@ -88,14 +92,14 @@ */ ACR_DECLARE(void) ACR_Sha1UpdateW(acr_sha1_ctx_t *context, const wchar_t *input, - unsigned int count); + size_t count); /** * Finish computing the SHA digest * @param digest the output buffer in which to store the digest * @param context The context to finalize */ -ACR_DECLARE(void) ACR_Sha1Final(unsigned char digest[ACR_SHA1_DIGESTSIZE], +ACR_DECLARE(void) ACR_Sha1Final(unsigned char digest[ACR_SHA1_DIGEST_LENGTH], acr_sha1_ctx_t *context); /** @@ -105,7 +109,7 @@ * @param len The length of the plaintext data * @param out The encrypted/encoded password */ -ACR_DECLARE(void) ACR_Sha1Base16A(const char *clear, int len, char *out); +ACR_DECLARE(char *) ACR_Sha1Base16A(const char *clear, size_t len, char *out); /** * Provide a means to SHA1 crypt/encode a plaintext data using @@ -114,7 +118,71 @@ * @param len The length of the plaintext data * @param out The encrypted/encoded password */ -ACR_DECLARE(void) ACR_Sha1Base16W(const wchar_t *clear, int len, wchar_t *out); +ACR_DECLARE(wchar_t *) ACR_Sha1Base16W(const wchar_t *clear, size_t len, + wchar_t *out); + +/** + * Initialize the MD5 digest + * @param context The MD5 context to initialize + */ +ACR_DECLARE(void) ACR_Md5Init(acr_md5_ctx_t *ctx); + +/** + * Update the MD5 digest with binary data + * @param context The MD5 context to update + * @param input The buffer to add to the MD5 digest + * @param count The length of the input buffer + */ +ACR_DECLARE(void) ACR_Md5Update(acr_md5_ctx_t *ctx, + const unsigned char *input, + size_t count); + +/** + * Update the MD5 digest + * @param context The MD5 context to update + * @param input The buffer to add to the MD5 digest + * @param count The length of the input buffer + */ +ACR_DECLARE(void) ACR_Md5UpdateA(acr_md5_ctx_t *context, + const char *input, + size_t count); + +/** + * Update the MD5 digest + * @param context The MD5 context to update + * @param input The buffer to add to the MD5 digest + * @param count The length of the input buffer + */ +ACR_DECLARE(void) ACR_Md5UpdateW(acr_md5_ctx_t *context, + const wchar_t *input, + size_t count); + +/** + * Finish computing the MD5 digest + * @param digest the output buffer in which to store the digest + * @param context The context to finalize + */ +ACR_DECLARE(void) ACR_Md5Final(unsigned char digest[ACR_MD5_DIGEST_LENGTH], + acr_md5_ctx_t *context); + +/** + * Provide a means to MD5 crypt/encode a plaintext data using + * base 16 encoding. + * @param clear The plaintext data. + * @param len The length of the plaintext data + * @param out The encrypted/encoded password + */ +ACR_DECLARE(char *) ACR_Md5Base16A(const char *clear, size_t len, char *out); + +/** + * Provide a means to MD5 crypt/encode a plaintext data using + * base 16 encoding. + * @param clear The plaintext data. + * @param len The length of the plaintext data + * @param out The encrypted/encoded password + */ +ACR_DECLARE(wchar_t *) ACR_Md5Base16W(const wchar_t *clear, size_t len, + wchar_t *out); #ifdef __cplusplus } Added: commons/sandbox/runtime/trunk/src/main/native/shared/md5.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/md5.c?rev=802177&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/md5.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/shared/md5.c Fri Aug 7 20:45:48 2009 @@ -0,0 +1,330 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 "acr.h" +#include "acr_private.h" +#include "acr_error.h" +#include "acr_string.h" +#include "acr_clazz.h" +#include "acr_crypto.h" + +static const char basis16[] = + "0123456789abcdef"; + +#define HI_NIBBLE_HEX(a) (basis16[((unsigned char)(a) >> 4)]) +#define LO_NIBBLE_HEX(a) (basis16[((unsigned char)(a) & 0x0F)]) + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value) >> 56; \ + (cp)[6] = (value) >> 48; \ + (cp)[5] = (value) >> 40; \ + (cp)[4] = (value) >> 32; \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +static acr_byte_t PADDING[ACR_MD5_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +ACR_DECLARE(void) ACR_Md5Init(acr_md5_ctx_t *ctx) +{ + ctx->count = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void +md5transform(acr_uint32_t state[4], + const acr_byte_t block[ACR_MD5_BLOCK_LENGTH]) +{ + acr_uint32_t a, b, c, d, in[ACR_MD5_BLOCK_LENGTH / 4]; + +#if !CC_IS_BIG_ENDIAN + memcpy(in, block, sizeof(in)); +#else + for (a = 0; a < ACR_MD5_BLOCK_LENGTH / 4; a++) { + in[a] = (acr_uint32_t)( + (acr_uint32_t)(block[a * 4 + 0]) | + (acr_uint32_t)(block[a * 4 + 1]) << 8 | + (acr_uint32_t)(block[a * 4 + 2]) << 16 | + (acr_uint32_t)(block[a * 4 + 3]) << 24); + } +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +ACR_DECLARE(void) +ACR_Md5Update(acr_md5_ctx_t *ctx, const unsigned char *input, size_t len) +{ + size_t have, need; + + /* Check how many bytes we already have and how many more we need. */ + have = (size_t)((ctx->count >> 3) & (ACR_MD5_BLOCK_LENGTH - 1)); + need = ACR_MD5_BLOCK_LENGTH - have; + + /* Update bitcount */ + ctx->count += (acr_uint64_t)len << 3; + + if (len >= need) { + if (have != 0) { + memcpy(ctx->buffer + have, input, need); + md5transform(ctx->state, ctx->buffer); + input += need; + len -= need; + have = 0; + } + + /* Process data in ACR_MD5_BLOCK_LENGTH-byte chunks. */ + while (len >= ACR_MD5_BLOCK_LENGTH) { + md5transform(ctx->state, input); + input += ACR_MD5_BLOCK_LENGTH; + len -= ACR_MD5_BLOCK_LENGTH; + } + } + + /* Handle any remaining bytes of data. */ + if (len != 0) + memcpy(ctx->buffer + have, input, len); +} + +ACR_DECLARE(void) ACR_Md5UpdateA(acr_md5_ctx_t *context, + const char *data, + size_t count) +{ + ACR_Md5Update(context, (const unsigned char *)data, count); +} + +ACR_DECLARE(void) ACR_Md5UpdateW(acr_md5_ctx_t *context, + const wchar_t *data, + size_t count) +{ + ACR_Md5Update(context, (const unsigned char *)data, + count * sizeof(wchar_t)); +} + +/* + * Pad pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void +md5pad(acr_md5_ctx_t *ctx) +{ + acr_byte_t count[8]; + size_t padlen; + + /* Convert count to 8 bytes in little endian order. */ + PUT_64BIT_LE(count, ctx->count); + + /* Pad out to 56 mod 64. */ + padlen = ACR_MD5_BLOCK_LENGTH - + ((ctx->count >> 3) & (ACR_MD5_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += ACR_MD5_BLOCK_LENGTH; + ACR_Md5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + ACR_Md5Update(ctx, count, 8); +} + +/* + * Final wrapup--call MD5Pad, fill in digest and zero out ctx. + */ +ACR_DECLARE(void) +ACR_Md5Final(unsigned char digest[ACR_MD5_DIGEST_LENGTH], acr_md5_ctx_t *ctx) +{ + int i; + + md5pad(ctx); + if (digest != NULL) { + for (i = 0; i < 4; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); + memset(ctx, 0, sizeof(*ctx)); + } +} + +ACR_DECLARE(char *) ACR_Md5Base16A(const char *clear, size_t len, char *out) +{ + int i, x = 0; + acr_md5_ctx_t context; + acr_byte_t digest[ACR_MD5_DIGEST_LENGTH]; + + if (out == NULL && (out = malloc(ACR_MD5_DIGEST_STRING_LENGTH)) == NULL) + return NULL; + + ACR_Md5Init(&context); + ACR_Md5UpdateA(&context, clear, len); + ACR_Md5Final(digest, &context); + for (i = 0; i < ACR_MD5_DIGEST_LENGTH; i++) { + out[x++] = HI_NIBBLE_HEX(digest[i]); + out[x++] = LO_NIBBLE_HEX(digest[i]); + } + out[x] = '\0'; + + memset(digest, 0, sizeof(digest)); + return out; +} + +ACR_DECLARE(wchar_t *) ACR_Md5Base16W(const wchar_t *clear, size_t len, wchar_t *out) +{ + int i, x = 0; + acr_md5_ctx_t context; + acr_byte_t digest[ACR_MD5_DIGEST_LENGTH]; + + if (out == NULL && + (out = malloc(ACR_MD5_DIGEST_STRING_LENGTH * sizeof(wchar_t))) == NULL) + return NULL; + ACR_Md5Init(&context); + ACR_Md5UpdateW(&context, clear, len); + ACR_Md5Final(digest, &context); + for (i = 0; i < ACR_MD5_DIGEST_LENGTH; i++) { + out[x++] = HI_NIBBLE_HEX(digest[i]); + out[x++] = LO_NIBBLE_HEX(digest[i]); + } + out[x] = L'\0'; + + memset(digest, 0, sizeof(digest)); + return out; +} + Propchange: commons/sandbox/runtime/trunk/src/main/native/shared/md5.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/shared/sha.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/sha.c?rev=802177&r1=802176&r2=802177&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/sha.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/sha.c Fri Aug 7 20:45:48 2009 @@ -15,6 +15,20 @@ */ /* + * SHA-1 in C + * By Steve Reid <st...@edmweb.com> + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +/* * * @author Mladen Turk */ @@ -32,254 +46,219 @@ #define HI_NIBBLE_HEX(a) (basis16[((unsigned char)(a) >> 4)]) #define LO_NIBBLE_HEX(a) (basis16[((unsigned char)(a) & 0x0F)]) -/* a bit faster & bigger, if defined */ -#define UNROLL_LOOPS - -/* NIST's proposed modification to SHA, 7/11/94 */ -#define USE_MODIFIED_SHA - -/* SHA f()-functions */ -#define f1(x,y,z) ((x & y) | (~x & z)) -#define f2(x,y,z) (x ^ y ^ z) -#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) -#define f4(x,y,z) (x ^ y ^ z) - -/* SHA constants */ -#define CONST1 0x5a827999L -#define CONST2 0x6ed9eba1L -#define CONST3 0x8f1bbcdcL -#define CONST4 0xca62c1d6L -/* 32-bit rotate */ +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) -#define ROT32(x,n) ((x << n) | (x >> (32 - n))) - -#define FUNC(n,i) \ - temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \ - E = D; D = C; C = ROT32(B,30); B = A; A = temp - -#define SHA_BLOCKSIZE 64 - -/* do SHA transformation */ -static void sha_transform(acr_sha1_ctx_t *context) -{ - int i; - acr_uint32_t temp, A, B, C, D, E, W[80]; +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +#if !CC_IS_BIG_ENDIAN +# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +# define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) - for (i = 0; i < 16; ++i) { - W[i] = context->data[i]; - } - for (i = 16; i < 80; ++i) { - W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; -#ifdef USE_MODIFIED_SHA - W[i] = ROT32(W[i], 1); -#endif /* USE_MODIFIED_SHA */ - } - A = context->digest[0]; - B = context->digest[1]; - C = context->digest[2]; - D = context->digest[3]; - E = context->digest[4]; - - FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4); - FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9); - FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14); - FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19); - - FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24); - FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29); - FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34); - FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39); - - FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44); - FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49); - FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54); - FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59); - - FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64); - FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69); - FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74); - FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79); - - context->digest[0] += A; - context->digest[1] += B; - context->digest[2] += C; - context->digest[3] += D; - context->digest[4] += E; -} +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +typedef union { + acr_byte_t c[64]; + acr_uint32_t l[16]; +} CHAR64LONG16; -#if !CC_IS_BIG_ENDIAN -/* Change endianness of data. - * count is the number of bytes to do an endian flip +/* + * Hash a single 512-bit block. This is the core of the algorithm. */ -static void byte_reverse(acr_uint32_t *buffer, int count) -{ - int i; - acr_byte_t ct[4], *cp; +static void +sha1transform(acr_uint32_t state[5], + const acr_byte_t buffer[ACR_SHA1_BLOCK_LENGTH]) +{ + acr_uint32_t a, b, c, d, e; + acr_byte_t workspace[ACR_SHA1_BLOCK_LENGTH]; + CHAR64LONG16 *block = (CHAR64LONG16 *)workspace; + + (void)memcpy(block, buffer, ACR_SHA1_BLOCK_LENGTH); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; - count /= sizeof(acr_uint32_t); - cp = (acr_byte_t *) buffer; - for (i = 0; i < count; ++i) { - ct[0] = cp[0]; - ct[1] = cp[1]; - ct[2] = cp[2]; - ct[3] = cp[3]; - cp[0] = ct[3]; - cp[1] = ct[2]; - cp[2] = ct[1]; - cp[3] = ct[0]; - cp += sizeof(acr_uint32_t); - } + /* Wipe variables */ + a = b = c = d = e = 0; } -#endif /* initialize the SHA digest */ ACR_DECLARE(void) ACR_Sha1Init(acr_sha1_ctx_t *context) { - context->digest[0] = 0x67452301L; - context->digest[1] = 0xefcdab89L; - context->digest[2] = 0x98badcfeL; - context->digest[3] = 0x10325476L; - context->digest[4] = 0xc3d2e1f0L; - context->count_lo = 0L; - context->count_hi = 0L; - context->local = 0; + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; } /* * Update the SHA digest */ ACR_DECLARE(void) ACR_Sha1Update(acr_sha1_ctx_t *context, - const unsigned char *buffer, - unsigned int count) + const unsigned char *data, + size_t len) { - unsigned int i; + size_t i, j; - if ((context->count_lo + ((acr_uint32_t) count << 3)) < context->count_lo) { - ++context->count_hi; + j = (size_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64-j)); + sha1transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + sha1transform(context->state, (acr_byte_t *)&data[i]); + j = 0; + } else { + i = 0; } - context->count_lo += (acr_uint32_t) count << 3; - context->count_hi += (acr_uint32_t) count >> 29; - if (context->local) { - i = SHA_BLOCKSIZE - context->local; - if (i > count) { - i = count; - } - memcpy(((acr_byte_t *) context->data) + context->local, buffer, i); - count -= i; - buffer += i; - context->local += i; - if (context->local == SHA_BLOCKSIZE) { -#if !CC_IS_BIG_ENDIAN - byte_reverse(context->data, SHA_BLOCKSIZE); -#endif - sha_transform(context); - } - else { - return; - } - } - while (count >= SHA_BLOCKSIZE) { - memcpy(context->data, buffer, SHA_BLOCKSIZE); - buffer += SHA_BLOCKSIZE; - count -= SHA_BLOCKSIZE; -#if !CC_IS_BIG_ENDIAN - byte_reverse(context->data, SHA_BLOCKSIZE); -#endif - sha_transform(context); - } - memcpy(context->data, buffer, count); - context->local = count; + memcpy(&context->buffer[j], &data[i], len - i); } ACR_DECLARE(void) ACR_Sha1UpdateA(acr_sha1_ctx_t *context, - const char *buf, - unsigned int count) + const char *data, + size_t count) { - ACR_Sha1Update(context, (const unsigned char *)buf, count); + ACR_Sha1Update(context, (const unsigned char *)data, count); } ACR_DECLARE(void) ACR_Sha1UpdateW(acr_sha1_ctx_t *context, - const wchar_t *buf, - unsigned int count) + const wchar_t *data, + size_t count) { - ACR_Sha1Update(context, (const unsigned char *)buf, + ACR_Sha1Update(context, (const unsigned char *)data, count * sizeof(wchar_t)); } +/* + * Add padding and return the message digest. + */ +static void sha1pad(acr_sha1_ctx_t *context) +{ + acr_byte_t finalcount[8]; + u_int i; + + for (i = 0; i < 8; i++) { + finalcount[i] = (acr_byte_t)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + ACR_Sha1Update(context, (acr_byte_t *)"\200", 1); + while ((context->count & 504) != 448) + ACR_Sha1Update(context, (acr_byte_t *)"\0", 1); + ACR_Sha1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ +} + /* * Finish computing the SHA digest */ -ACR_DECLARE(void) ACR_Sha1Final(unsigned char digest[ACR_SHA1_DIGESTSIZE], +ACR_DECLARE(void) ACR_Sha1Final(unsigned char digest[ACR_SHA1_DIGEST_LENGTH], acr_sha1_ctx_t *context) { - int count, i, j; - acr_uint32_t lo_bit_count, hi_bit_count, k; - - lo_bit_count = context->count_lo; - hi_bit_count = context->count_hi; - count = (int) ((lo_bit_count >> 3) & 0x3f); - ((acr_byte_t *) context->data)[count++] = 0x80; + unsigned int i; - if (count > SHA_BLOCKSIZE - 8) { - memset(((acr_byte_t *) context->data) + count, 0, SHA_BLOCKSIZE - count); -#if !CC_IS_BIG_ENDIAN - byte_reverse(context->data, SHA_BLOCKSIZE); -#endif - sha_transform(context); - memset((acr_byte_t *) context->data, 0, SHA_BLOCKSIZE - 8); - } - else { - memset(((acr_byte_t *) context->data) + count, 0, - SHA_BLOCKSIZE - 8 - count); - } -#if !CC_IS_BIG_ENDIAN - byte_reverse(context->data, SHA_BLOCKSIZE); -#endif - context->data[14] = hi_bit_count; - context->data[15] = lo_bit_count; - sha_transform(context); - - for (i = 0, j = 0; j < ACR_SHA1_DIGESTSIZE; i++) { - k = context->digest[i]; - digest[j++] = (unsigned char)((k >> 24) & 0xff); - digest[j++] = (unsigned char)((k >> 16) & 0xff); - digest[j++] = (unsigned char)((k >> 8 ) & 0xff); - digest[j++] = (unsigned char)( k & 0xff); + sha1pad(context); + if (digest) { + for (i = 0; i < ACR_SHA1_DIGEST_LENGTH; i++) { + digest[i] = (acr_byte_t) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + memset(context, 0, sizeof(*context)); } } -ACR_DECLARE(void) ACR_Sha1Base16A(const char *clear, int len, char *out) +ACR_DECLARE(char *) ACR_Sha1Base16A(const char *clear, size_t len, char *out) { int i, x = 0; acr_sha1_ctx_t context; - acr_byte_t digest[ACR_SHA1_DIGESTSIZE]; + acr_byte_t digest[ACR_SHA1_DIGEST_LENGTH]; + + if (out == NULL && (out = malloc(ACR_SHA1_DIGEST_STRING_LENGTH)) == NULL) + return NULL; ACR_Sha1Init(&context); ACR_Sha1UpdateA(&context, clear, len); ACR_Sha1Final(digest, &context); - for (i = 0; i < ACR_SHA1_DIGESTSIZE; i++) { + for (i = 0; i < ACR_SHA1_DIGEST_LENGTH; i++) { out[x++] = HI_NIBBLE_HEX(digest[i]); out[x++] = LO_NIBBLE_HEX(digest[i]); } out[x] = '\0'; + memset(digest, 0, sizeof(digest)); + return out; } -ACR_DECLARE(void) ACR_Sha1Base16W(const wchar_t *clear, int len, wchar_t *out) +ACR_DECLARE(wchar_t *) ACR_Sha1Base16W(const wchar_t *clear, size_t len, + wchar_t *out) { int i, x = 0; acr_sha1_ctx_t context; - acr_byte_t digest[ACR_SHA1_DIGESTSIZE]; + acr_byte_t digest[ACR_SHA1_DIGEST_LENGTH]; + + if (out == NULL && + (out = malloc(ACR_SHA1_DIGEST_STRING_LENGTH * sizeof(wchar_t))) == NULL) + return NULL; ACR_Sha1Init(&context); ACR_Sha1UpdateW(&context, clear, len); ACR_Sha1Final(digest, &context); - for (i = 0; i < ACR_SHA1_DIGESTSIZE; i++) { + for (i = 0; i < ACR_SHA1_DIGEST_LENGTH; i++) { out[x++] = HI_NIBBLE_HEX(digest[i]); out[x++] = LO_NIBBLE_HEX(digest[i]); } out[x] = L'\0'; + + memset(digest, 0, sizeof(digest)); + return out; }