diff --git a/Android/jni/apple2ix.mk b/Android/jni/apple2ix.mk index 08c0799a..69260623 100644 --- a/Android/jni/apple2ix.mk +++ b/Android/jni/apple2ix.mk @@ -12,7 +12,7 @@ include $(COMMON_SOURCES_MK) LOCAL_MODULE := apple2ix LOCAL_SRC_FILES := jnihooks.c -LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=0 -DVIDEO_OPENGL=1 -DDEBUGGER=0 -DHAVE_OPENSSL=0 +LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=0 -DVIDEO_OPENGL=1 -DDEBUGGER=0 LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lz # Add assembly files first ... mostly for the benefit of the ARM assembler ... diff --git a/Android/jni/sources.mk b/Android/jni/sources.mk index dda72a1c..cda251cf 100644 --- a/Android/jni/sources.mk +++ b/Android/jni/sources.mk @@ -23,7 +23,8 @@ APPLE2_AUDIO_SRC = \ $(APPLE2_SRC_PATH)/audio/AY8910.c APPLE2_META_SRC = \ - $(APPLE2_SRC_PATH)/meta/debug.c $(APPLE2_SRC_PATH)/meta/debugger.c $(APPLE2_SRC_PATH)/meta/opcodes.c + $(APPLE2_SRC_PATH)/meta/debug.c $(APPLE2_SRC_PATH)/meta/debugger.c $(APPLE2_SRC_PATH)/meta/opcodes.c \ + $(APPLE2_SRC_PATH)/test/sha.c APPLE2_MAIN_SRC = \ $(APPLE2_SRC_PATH)/font.c $(APPLE2_SRC_PATH)/rom.c $(APPLE2_SRC_PATH)/misc.c $(APPLE2_SRC_PATH)/display.c $(APPLE2_SRC_PATH)/vm.c \ diff --git a/Android/jni/testcpu.mk b/Android/jni/testcpu.mk index 56212fd4..3e729f01 100644 --- a/Android/jni/testcpu.mk +++ b/Android/jni/testcpu.mk @@ -12,7 +12,7 @@ include $(COMMON_SOURCES_MK) LOCAL_MODULE := apple2ix LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/test/testcommon.c $(APPLE2_SRC_PATH)/test/testcpu.c -LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=1 -DDEBUGGER=1 -DHAVE_OPENSSL=0 +LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) -DHEADLESS=1 -DDEBUGGER=1 LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lz # Add assembly files first ... mostly for the benefit of the ARM assembler ... diff --git a/Makefile.am b/Makefile.am index eae9501a..464d208f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,8 @@ AUDIO_SRC = \ src/audio/AY8910.c META_SRC = \ - src/meta/debug.l src/meta/debugger.c src/meta/opcodes.c + src/meta/debug.l src/meta/debugger.c src/meta/opcodes.c \ + src/test/sha1.c # NOTE : selectively enabled through configuration process ... EXTRA_apple2ix_SOURCES = \ diff --git a/configure.ac b/configure.ac index 5950e4d6..16c8fb37 100644 --- a/configure.ac +++ b/configure.ac @@ -256,19 +256,7 @@ dnl --------------------------------------------------------------------------- dnl Debugger & classic interface ... AC_ARG_ENABLE([debugger], AS_HELP_STRING([--disable-debugger], [Disable 6502 debugging console]), [], [ AC_DEFINE(DEBUGGER, 1, [Enable 6502 debugger module]) - META_O="src/meta/debug.o src/meta/debugger.o src/meta/opcodes.o" - - AC_CHECK_HEADER(openssl/sha.h, [ - AC_SEARCH_LIBS(SHA1, crypto, [ - AC_DEFINE(HAVE_OPENSSL, 1, [Use OpenSSL]) - ], [ - AC_MSG_WARN([Could not find OpenSSL libraries, certain functionality will be disabled]) - ], []) - ], [ - AC_MSG_WARN([Could not find openssl/sha.h header]) - ], [ -#include - ]) + META_O="src/meta/debug.o src/meta/debugger.o src/meta/opcodes.o src/test/sha1.o" ]) AC_SUBST(META_O) diff --git a/src/meta/debugger.c b/src/meta/debugger.c index 20d95383..f721244f 100644 --- a/src/meta/debugger.c +++ b/src/meta/debugger.c @@ -16,9 +16,7 @@ #include "common.h" -#if HAVE_OPENSSL -#include -#endif +#include #define SW_TEXT 0xC050 #define SW_MIXED 0xC052 @@ -1100,7 +1098,6 @@ void clear_debugger_screen() { fb_sha1 () -- prints SHA1 of the current Apple // framebuffer ------------------------------------------------------------------------- */ void fb_sha1() { -#if HAVE_OPENSSL uint8_t md[SHA_DIGEST_LENGTH]; char buf[(SHA_DIGEST_LENGTH*2)+1]; @@ -1124,9 +1121,6 @@ void fb_sha1() { clear_debugger_screen(); sprintf(second_buf[num_buffer_lines++], "%s", buf); -#else - sprintf(second_buf[num_buffer_lines++], "SHA1 unavailable, not built with OpenSSL"); -#endif } /* ------------------------------------------------------------------------- diff --git a/src/test/sha1-license.txt b/src/test/sha1-license.txt new file mode 100644 index 00000000..8d7f3941 --- /dev/null +++ b/src/test/sha1-license.txt @@ -0,0 +1,14 @@ +Copyright (C) 1998, 2009 +Paul E. Jones + +Freeware Public License (FPL) + +This software is licensed as "freeware." Permission to distribute +this software in source and binary forms, including incorporation +into other products, is hereby granted without a fee. THIS SOFTWARE +IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD +LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER +DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA +OR DATA BEING RENDERED INACCURATE. diff --git a/src/test/sha1.c b/src/test/sha1.c new file mode 100644 index 00000000..2e04b2e1 --- /dev/null +++ b/src/test/sha1.c @@ -0,0 +1,395 @@ +/* + * sha1.c + * + * Copyright (C) 1998, 2009 + * Paul E. Jones + * All Rights Reserved + * + ***************************************************************************** + * $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $ + ***************************************************************************** + * + * Description: + * This file implements the Secure Hashing Standard as defined + * in FIPS PUB 180-1 published April 17, 1995. + * + * The Secure Hashing Standard, which uses the Secure Hashing + * Algorithm (SHA), produces a 160-bit message digest for a + * given data stream. In theory, it is highly improbable that + * two messages will produce the same message digest. Therefore, + * this algorithm can serve as a means of providing a "fingerprint" + * for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code was + * written with the expectation that the processor has at least + * a 32-bit machine word size. If the machine word size is larger, + * the code should still function properly. One caveat to that + * is that the input functions taking characters and character + * arrays assume that only 8 bits of information are stored in each + * character. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated for + * messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is a + * multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the circular shift macro + */ +#define SHA1CircularShift(bits,word) \ + ((((word) << (bits)) & 0xFFFFFFFF) | \ + ((word) >> (32-(bits)))) + +/* Function prototypes */ +void SHA1ProcessMessageBlock(SHA1Context *); +void SHA1PadMessage(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1Reset(SHA1Context *context) +{ + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Message_Digest[0] = 0x67452301; + context->Message_Digest[1] = 0xEFCDAB89; + context->Message_Digest[2] = 0x98BADCFE; + context->Message_Digest[3] = 0x10325476; + context->Message_Digest[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array within the SHA1Context provided + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * + * Returns: + * 1 if successful, 0 if it failed. + * + * Comments: + * + */ +int SHA1Result(SHA1Context *context) +{ + + if (context->Corrupted) + { + return 0; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + context->Computed = 1; + } + + return 1; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion of + * the message. + * + * Parameters: + * context: [in/out] + * The SHA-1 context to update + * message_array: [in] + * An array of characters representing the next portion of the + * message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1Input( SHA1Context *context, + const unsigned char *message_array, + unsigned length) +{ + if (!length) + { + return; + } + + if (context->Computed || context->Corrupted) + { + context->Corrupted = 1; + return; + } + + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + /* Force it to 32 bits */ + context->Length_Low &= 0xFFFFFFFF; + if (context->Length_Low == 0) + { + context->Length_High++; + /* Force it to 32 bits */ + context->Length_High &= 0xFFFFFFFF; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in the SHAContext, especially the + * single character names, were used because those were the names + * used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const unsigned K[] = /* Constants defined in SHA-1 */ + { + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + unsigned temp; /* Temporary word value */ + unsigned W[80]; /* Word sequence */ + unsigned A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Message_Digest[0]; + B = context->Message_Digest[1]; + C = context->Message_Digest[2]; + D = context->Message_Digest[3]; + E = context->Message_Digest[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Message_Digest[0] = + (context->Message_Digest[0] + A) & 0xFFFFFFFF; + context->Message_Digest[1] = + (context->Message_Digest[1] + B) & 0xFFFFFFFF; + context->Message_Digest[2] = + (context->Message_Digest[2] + C) & 0xFFFFFFFF; + context->Message_Digest[3] = + (context->Message_Digest[3] + D) & 0xFFFFFFFF; + context->Message_Digest[4] = + (context->Message_Digest[4] + E) & 0xFFFFFFFF; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call SHA1ProcessMessageBlock() + * appropriately. When it returns, it can be assumed that the + * message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * + * Returns: + * Nothing. + * + * Comments: + * + */ +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; + context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; + context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; + context->Message_Block[59] = (context->Length_High) & 0xFF; + context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; + context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; + context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; + context->Message_Block[63] = (context->Length_Low) & 0xFF; + + SHA1ProcessMessageBlock(context); +} + +#ifdef APPLE2IX +void SHA1(const unsigned char *d, size_t n, unsigned char *md) { + SHA1Context sha = { { 0 } }; + SHA1Reset(&sha); + SHA1Input(&sha, d, n); + if (!SHA1Result(&sha)) { + memset(md, '\0', SHA_DIGEST_LENGTH); + } else { + // Assuming LE for now + unsigned char *ptr = md; + for (int i=0; i<5; i++) { + unsigned char *b = (unsigned char *)&sha.Message_Digest[i]; + b+=3; + for (int j=0; j<4; j++) { + *ptr = *b; + ++ptr; + --b; + } + } + } +} +#endif + diff --git a/src/test/sha1.h b/src/test/sha1.h new file mode 100644 index 00000000..c1a3eb12 --- /dev/null +++ b/src/test/sha1.h @@ -0,0 +1,64 @@ +/* + * sha1.h + * + * Copyright (C) 1998, 2009 + * Paul E. Jones + * All Rights Reserved + * + ***************************************************************************** + * $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $ + ***************************************************************************** + * + * Description: + * This class implements the Secure Hashing Standard as defined + * in FIPS PUB 180-1 published April 17, 1995. + * + * Many of the variable names in the SHA1Context, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#ifdef APPLE2IX +#include +#include +#endif + +/* + * This structure will hold context information for the hashing + * operation + */ +typedef struct SHA1Context +{ + unsigned Message_Digest[5]; /* Message Digest (output) */ + + unsigned Length_Low; /* Message length in bits */ + unsigned Length_High; /* Message length in bits */ + + unsigned char Message_Block[64]; /* 512-bit message blocks */ + int Message_Block_Index; /* Index into message block array */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corruped? */ +} SHA1Context; + +/* + * Function Prototypes + */ +void SHA1Reset(SHA1Context *); +int SHA1Result(SHA1Context *); +void SHA1Input( SHA1Context *, + const unsigned char *, + unsigned); + +#ifdef APPLE2IX +# define SHA_DIGEST_LENGTH 20 +void SHA1(const unsigned char *d, size_t n, unsigned char *md); +#endif + +#endif diff --git a/src/test/shatest.c b/src/test/shatest.c new file mode 100644 index 00000000..c1ca6d07 --- /dev/null +++ b/src/test/shatest.c @@ -0,0 +1,114 @@ +/* + * shatest.c + * + * Copyright (C) 1998, 2009 + * Paul E. Jones + * All Rights Reserved + * + ***************************************************************************** + * $Id: shatest.c 12 2009-06-22 19:34:25Z paulej $ + ***************************************************************************** + * + * Description: + * This file will exercise the SHA1 class and perform the three + * tests documented in FIPS PUB 180-1. + * + * Portability Issues: + * None. + * + */ + +#include +#include +#include "sha1.h" + +/* + * Define patterns for testing + */ +#define TESTA "abc" +#define TESTB_1 "abcdbcdecdefdefgefghfghighij" +#define TESTB_2 "hijkijkljklmklmnlmnomnopnopq" +#define TESTB TESTB_1 TESTB_2 +#define TESTC "a" + +int main() +{ + SHA1Context sha; + int i; + + /* + * Perform test A + */ + printf("\nTest A: 'abc'\n"); + + SHA1Reset(&sha); + SHA1Input(&sha, (const unsigned char *) TESTA, strlen(TESTA)); + + if (!SHA1Result(&sha)) + { + fprintf(stderr, "ERROR-- could not compute message digest\n"); + } + else + { + printf("\t"); + for(i = 0; i < 5 ; i++) + { + printf("%X ", sha.Message_Digest[i]); + } + printf("\n"); + printf("Should match:\n"); + printf("\tA9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n"); + } + + /* + * Perform test B + */ + printf("\nTest B:\n"); + + SHA1Reset(&sha); + SHA1Input(&sha, (const unsigned char *) TESTB, strlen(TESTB)); + + if (!SHA1Result(&sha)) + { + fprintf(stderr, "ERROR-- could not compute message digest\n"); + } + else + { + printf("\t"); + for(i = 0; i < 5 ; i++) + { + printf("%X ", sha.Message_Digest[i]); + } + printf("\n"); + printf("Should match:\n"); + printf("\t84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n"); + } + + /* + * Perform test C + */ + printf("\nTest C: One million 'a' characters\n"); + + SHA1Reset(&sha); + for(i = 1; i <= 1000000; i++) { + SHA1Input(&sha, (const unsigned char *) TESTC, 1); + } + + if (!SHA1Result(&sha)) + { + fprintf(stderr, "ERROR-- could not compute message digest\n"); + } + else + { + printf("\t"); + for(i = 0; i < 5 ; i++) + { + printf("%X ", sha.Message_Digest[i]); + } + printf("\n"); + printf("Should match:\n"); + printf("\t34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n"); + } + + return 0; +} diff --git a/src/test/testcommon.h b/src/test/testcommon.h index fe576783..4c54b76f 100644 --- a/src/test/testcommon.h +++ b/src/test/testcommon.h @@ -19,10 +19,8 @@ # include # define SHA_DIGEST_LENGTH CC_SHA1_DIGEST_LENGTH # define SHA1 CC_SHA1 -#elif HAVE_OPENSSL -# include #else -# error "these tests require OpenSSL libraries (SHA)" +# include "test/sha1.h" #endif #define TEST_FINISHED 0xff