diff --git a/Makefile b/Makefile index d293d18..eb681fd 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS = -O255 -w255 LIBRARIES = lib65816crypto lib65816hash PROGRAMS = aescbctest aesctrtest aestest aescrypt sha1sum sha1test \ - sha256sum sha256test md5sum md5test hmactest + sha256sum sha256test md5sum md5test md4sum md4test hmactest .PHONY: default default: $(LIBRARIES) $(PROGRAMS) @@ -33,11 +33,15 @@ md5.a: md5.cc md5.h md5.asm md5.macros hmacimpl.h $(CC) $(CFLAGS) -c $< md5.B: md5.a +md4.a: md4.cc md4.h md4.asm md4.macros hmacimpl.h + $(CC) $(CFLAGS) -c $< +md4.B: md4.a + # Libraries lib65816crypto: aesmodes.a aes.a rm -f $@ iix makelib -P $@ $(patsubst %,+%,$^) -lib65816hash: sha1.a sha1.B sha256.a sha256.B md5.a md5.B +lib65816hash: sha1.a sha1.B sha256.a sha256.B md5.a md5.B md4.a md4.B rm -f $@ iix makelib -P $@ $(patsubst %,+%,$^) @@ -66,7 +70,12 @@ md5sum.a: md5sum.c md5.h cksumcommon.h md5test.a: md5test.c md5.h $(CC) $(CFLAGS) -c $< -hmactest.a: hmactest.c sha256.h sha1.h md5.h +md4sum.a: md4sum.c md4.h cksumcommon.h + $(CC) $(CFLAGS) -c $< +md4test.a: md4test.c md4.h + $(CC) $(CFLAGS) -c $< + +hmactest.a: hmactest.c sha256.h sha1.h md5.h md4.h $(CC) $(CFLAGS) -c $< aescbctest: aescbctest.a pagealign.root lib65816crypto @@ -93,6 +102,11 @@ md5sum: md5sum.a pagealign.root lib65816hash md5test: md5test.a pagealign.root lib65816hash $(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@ +md4sum: md4sum.a pagealign.root lib65816hash + $(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@ +md4test: md4test.a pagealign.root lib65816hash + $(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@ + hmactest: hmactest.a lib65816hash $(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@ diff --git a/README.md b/README.md index ccfb52f..7beae57 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ 65816 Cryptographic & Hash Libraries ==================================== -This package contains libraries implementing cryptographic algorithms for the 65816, suitable for use on the Apple IIgs and potentially also other 65816-based systems. Currently, it includes implementations of AES encryption and decryption (in `lib65816crypto`), and of the MD5, SHA-1, and SHA-256 hash functions (in `lib65816hash`). The core algorithms for each of these are written in carefully optimized assembly code, and they can generally process at least several thousand bytes per second on a 2.8 MHz Apple IIgs. +This package contains libraries implementing cryptographic algorithms for the 65816, suitable for use on the Apple IIgs and potentially also other 65816-based systems. Currently, it includes implementations of AES encryption and decryption (in `lib65816crypto`), and of the MD4, MD5, SHA-1, and SHA-256 hash functions (in `lib65816hash`). The core algorithms for each of these are written in carefully optimized assembly code, and they can generally process at least several thousand bytes per second on a 2.8 MHz Apple IIgs. Using the Libraries ------------------- @@ -11,11 +11,11 @@ If you are calling these algorithms from assembly language, simply follow the us If you use these libraries in your program, you will need to link them into it. You can either place the libraries in the `Libraries` directory of your ORCA installation, or place them somewhere else and specify them on the command line when linking your program. When using certain algorithms (currently AES and MD5), you may also need to include `pagealign.root` as the first file on the linker command line. This file contains no code, but simply specifies that the default load segment should be page-aligned. This is needed because those algorithms include data tables that are page-aligned to maximize performance. -Note that some of the algorithms implemented in this package (including MD5 and SHA-1) have known security weaknesses. If you are using them in a situation where security is important, you should refer to up-to-date cryptanalytic results and advice to determine whether they are appropriate for your application. +Note that some of the algorithms implemented in this package (including MD4, MD5, and SHA-1) have known security weaknesses. If you are using them in a situation where security is important, you should refer to up-to-date cryptanalytic results and advice to determine whether they are appropriate for your application. Building the Libraries ---------------------- -If you want to build these libraries yourself, you will need ORCA/M and ORCA/C. To ensure everything builds correctly, I recommend using [ORCA/C 2.2.0 B1 or later][1]. The included `Makefile` is set up to build the libraries and test programs on a modern system using [Golden Gate][2], but they could also be build under the ORCA shell or GNO with a suitable build script. +If you want to build these libraries yourself, you will need ORCA/M and ORCA/C. To ensure everything builds correctly, I recommend using [ORCA/C 2.2.0 or later][1]. The included `Makefile` is set up to build the libraries and test programs on a modern system using [Golden Gate][2], but they could also be build under the ORCA shell or GNO with a suitable build script. [1]: https://github.com/byteworksinc/ORCA-C/releases [2]: http://golden-gate.ksherlock.com diff --git a/hmactest.c b/hmactest.c index ea8ec9d..d733837 100644 --- a/hmactest.c +++ b/hmactest.c @@ -21,12 +21,14 @@ #include "sha256.h" #include "sha1.h" #include "md5.h" +#include "md4.h" int main(void) { Handle context_hndl; struct hmac_sha256_context *hmac_sha256_context; struct hmac_sha1_context *hmac_sha1_context; struct hmac_md5_context *hmac_md5_context; + struct hmac_md4_context *hmac_md4_context; char key[] = "key"; char msg[] = "The quick brown fox jumps over the lazy dog"; @@ -68,4 +70,15 @@ int main(void) { printf("%02x", hmac_md5_context->u[0].ctx.hash[i]); } printf("\n"); + + + hmac_md4_context = (struct hmac_md4_context *)*context_hndl; + hmac_md4_init(hmac_md4_context, key, sizeof(key)-1); + hmac_md4_compute(hmac_md4_context, msg, sizeof(msg)-1); + + printf("HMAC-MD4: "); + for (int i = 0; i < sizeof(hmac_md4_context->u[0].ctx.hash); i++) { + printf("%02x", hmac_md4_context->u[0].ctx.hash[i]); + } + printf("\n"); } diff --git a/md4.asm b/md4.asm new file mode 100644 index 0000000..bd366f4 --- /dev/null +++ b/md4.asm @@ -0,0 +1,153 @@ +* Copyright (c) 2017,2023 Stephen Heumann +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +* Implementation of the md4 hash function for the 65816 + + case on + mcopy md4.macros + +* Direct page locations +length gequ 0 +extra gequ 8 +idx gequ 10 +a_ gequ 12 ; elements of state +b gequ 16 +c gequ 20 +d gequ 24 +zero1 gequ 28 +temp gequ 30 +zero2 gequ 34 +;unused gequ 36 +h0 gequ 40 +h1 gequ 44 +h2 gequ 48 +h3 gequ 52 +;unused gequ 56 +m gequ 60 + + +* Precomputed values of g*4 for each loop iteration, for indexing the message +; align 256 +g_times_4 private + dc i2' 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60' + dc i2' 0, 16, 32, 48, 4, 20, 36, 52, 8, 24, 40, 56, 12, 28, 44, 60' + dc i2' 0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60' + end + +* Initialize a md4 context. +* This must be called before any of the other md4 functions. +md4_init start + CFunction MD4_INIT + end + +MD4_INIT start + lda #$2301 + sta h0 + lda #$6745 + sta h0+2 + + lda #$AB89 + sta h1 + lda #$EFCD + sta h1+2 + + lda #$DCFE + sta h2 + lda #$98BA + sta h2+2 + + lda #$5476 + sta h3 + lda #$1032 + sta h3+2 + + stz length + stz length+2 + stz length+4 + stz length+6 + stz extra + + stz zero1 + stz zero2 + rtl + end + + +* Process one 64-byte block through the md4 hashing function. +* This is a low-level function; users should normally not call this directly. +md4_processblock start + CFunction MD4_PROCESSBLOCK + end + +MD4_PROCESSBLOCK start + lda h0 + sta a_ + lda h0+2 + sta a_+2 + + lda h1 + sta b + lda h1+2 + sta b+2 + + lda h2 + sta c + lda h2+2 + sta c+2 + + lda h3 + sta d + lda h3+2 + sta d+2 + + stz idx + BlockLoopPart 1 + BlockLoopPart 2 + BlockLoopPart 3 + + clc + lda h0 + adc a_ + sta h0 + lda h0+2 + adc a_+2 + sta h0+2 + + clc + lda h1 + adc b + sta h1 + lda h1+2 + adc b+2 + sta h1+2 + + clc + lda h2 + adc c + sta h2 + lda h2+2 + adc c+2 + sta h2+2 + + clc + lda h3 + adc d + sta h3 + lda h3+2 + adc d+2 + sta h3+2 + + rtl + end diff --git a/md4.cc b/md4.cc new file mode 100644 index 0000000..371cd12 --- /dev/null +++ b/md4.cc @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017,2023 Stephen Heumann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma noroot +#pragma lint -1 +#pragma optimize -1 + +#include "md4.h" +#include + +#define length_offset 0 +#define extra_offset 8 +#define hash_offset 40 +#define data_offset 60 + +extern void MD4_PROCESSBLOCK(void); + +/* + * Update a md4 context based on the specified data. + */ +void md4_update(struct md4_context *context, + const unsigned char *data, + unsigned long length) +{ + unsigned int extra = context->extra; + unsigned long oldlength = context->length; + + if ((context->length += length) < oldlength) + context->length2++; + + if (extra > 0) { + if (length >= 64 - extra) { + memcpy(&context->block[extra], data, 64 - extra); + asm { + phd + lda context + tcd + jsl MD4_PROCESSBLOCK + pld + } + length -= 64 - extra; + data += 64 - extra; + } else { + memcpy(&context->block[extra], data, length); + context->extra += length; + return; + } + } + + while (length >= 64) { + memcpy(&context->block, data, 64); + asm { + phd + lda context + tcd + jsl MD4_PROCESSBLOCK + pld + } + length -= 64; + data += 64; + } + + memcpy(&context->block, data, length); + context->extra = length; +} + + +/* + * Finish md4 processing and generate the final hash code. + */ +void md4_finalize(struct md4_context *context) +{ + unsigned int extra = context->extra; + + context->block[extra++] = 0x80; + + memset(&context->block[extra], 0, 64 - extra); + + if (extra > 64 - 8) { + asm { + phd + lda context + tcd + jsl MD4_PROCESSBLOCK + pld + } + memset(&context->block, 0, 64 - 8); + } + + asm { + phd + lda context + tcd + + /* Append total length in bits */ + asl length_offset + rol length_offset+2 + rol length_offset+4 + rol length_offset+6 + asl length_offset + rol length_offset+2 + rol length_offset+4 + rol length_offset+6 + asl length_offset + rol length_offset+2 + rol length_offset+4 + rol length_offset+6 + + lda length_offset + sta data_offset+56 + lda length_offset+2 + sta data_offset+58 + lda length_offset+4 + sta data_offset+60 + lda length_offset+6 + sta data_offset+62 + + /* Process final block */ + jsl MD4_PROCESSBLOCK + + pld + } +} + +#define HASH_ALG md4 +#include "hmacimpl.h" + +#append "md4.asm" diff --git a/md4.h b/md4.h new file mode 100644 index 0000000..52ee0f9 --- /dev/null +++ b/md4.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017,2023 Stephen Heumann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct md4_context { + unsigned long length; + unsigned long length2; + unsigned short extra; + unsigned char reserved1[30]; + unsigned char hash[16]; + unsigned char reserved2[4]; + unsigned char block[64]; +}; + +struct hmac_md4_context { + union { + struct md4_context ctx; + unsigned char k[64]; + } u[3]; + unsigned char inner_hash[16]; +}; + +/* + * The context structure must be in bank 0, preferably page-aligned. + */ + +/* + * Initialize a md4 context. + * This must be called before any of the other md4 functions. + */ +void md4_init(struct md4_context *context); + +/* + * Update a md4 context based on the specified data. + */ +void md4_update(struct md4_context *context, const unsigned char *data, unsigned long length); + +/* + * Finish md4 processing and generate the final hash code. + */ +void md4_finalize(struct md4_context *context); + +/* + * Process one 64-byte block through the md4 hashing function. + * This is a low-level function; users should normally not call this directly. + */ +void md4_processblock(struct md4_context *context); + +/* + * Initialize a context for HMAC-MD4 computation with a specified key. + * This must be called before any calls to hmac_md4_compute. After + * initialization, the context can be used to compute the HMAC for any + * number of messages. + */ +void hmac_md4_init(struct hmac_md4_context *context, + const unsigned char *key, + unsigned long key_length); + +/* + * Compute the HMAC-MD4 of a message, using an already-initialized context. + * The result will be in context->u[0].ctx.hash. + */ +void hmac_md4_compute(struct hmac_md4_context *context, + const unsigned char *message, + unsigned long message_length); diff --git a/md4.macros b/md4.macros new file mode 100644 index 0000000..7c6ae1e --- /dev/null +++ b/md4.macros @@ -0,0 +1,361 @@ +* Copyright (c) 2017,2023 Stephen Heumann +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +* Right-rotate 32-bit value in &loc (DP or 16-bit address) by &n positions + macro + ROTR4 &loc,&n + aif &n>16,.dorotl + lda &loc+2 + lcla &i +&i seta &n +.rotrloop + lsr a ;to set carry + ror &loc + ror &loc+2 +&i seta &i-1 + aif &i>0,.rotrloop + ago .end +.dorotl + ROTL4 &loc,32-&n +.end + mend + +* Expects the contents of &loc+2 to be loaded in A already + macro + ROTR4CONT &loc,&n + aif &n>16,.dorotl + lcla &i +&i seta &n +.rotrloop + lsr a ;to set carry + ror &loc + ror &loc+2 +&i seta &i-1 + aif &i>0,.rotrloop + ago .end +.dorotl + ROTL4 &loc,32-&n +.end + mend + +* Left-rotate 32-bit value in &loc (DP or 16-bit address) by &n positions + macro + ROTL4 &loc,&n + aif &n>16,.dorotr2 + lda &loc + lcla &i +&i seta &n +.rotlloop2 + asl a ;to set carry + rol &loc+2 + rol &loc +&i seta &i-1 + aif &i>0,.rotlloop2 + ago .end2 +.dorotr2 + ROTR4 &loc,32-&n +.end2 + mend + +* Expects the contents of &loc to be loaded in A already + macro + ROTL4CONT &loc,&n + aif &n>16,.dorotr2 + lcla &i +&i seta &n +.rotlloop2 + asl a ;to set carry + rol &loc+2 + rol &loc +&i seta &i-1 + aif &i>0,.rotlloop2 + ago .end2 +.dorotr2 + ROTR4 &loc,32-&n +.end2 + mend + +* &to := &from ROTR4 &n + macro + ROTR4MOVE &to,&from,&n + aif &n>16,.dorotl3 + lda &from + sta &to + lda &from+2 + sta &to+2 + lcla &i +&i seta &n +.rotrloop3 + lsr a ;to set carry + ror &to + ror &to+2 +&i seta &i-1 + aif &i>0,.rotrloop3 + ago .end3 +.dorotl3 + ROTL4MOVE &to,&from,32-&n +.end3 + mend + +* &to := &from ROTL4 &n + macro + ROTL4MOVE &to,&from,&n + aif &n>16,.dorotr4 + lda &from+2 + sta &to+2 + lda &from + sta &to + lcla &i +&i seta &n +.rotlloop4 + asl a ;to set carry + rol &to+2 + rol &to +&i seta &i-1 + aif &i>0,.rotlloop4 + ago .end4 +.dorotr4 + ROTR4MOVE &to,&from,32-&n +.end4 + mend + +* Left-rotate with various optimizations applied + macro + ROTL4AUTO &loc,&n,&haveLocPlus2 + aif &n>4,.skip1 + ROTL4 &loc,&n + mexit +.skip1 + aif &n>7,.skip2 + ldx &loc+1 + lda &loc+3 + ora &loc-1 + sta &loc + stx &loc+2 + txa + ROTR4CONT &loc,8-&n + mexit +.skip2 + aif &n>11,.skip3 + ldx &loc+1 + lda &loc+3 + ora &loc-1 + sta &loc + stx &loc+2 + ROTL4CONT &loc,&n-8 + mexit +.skip3 + aif &n>15,.skip4 + aif C:&haveLocPlus2>0,.noload1 + ldy &loc+2 + ago .didload1 +.noload1 + tay +.didload1 + lda &loc + sta &loc+2 + sty &loc + ROTR4CONT &loc,16-&n + mexit +.skip4 + aif &n>16,.skip5 + aif C:&haveLocPlus2>0,.noload2 + lda &loc+2 +.noload2 + ldy &loc + sta &loc + sty &loc+2 + mexit +.skip5 + aif &n>20,.skip6 + aif C:&haveLocPlus2>0,.noload2 + lda &loc+2 +.noload2 + ldy &loc + sta &loc + sty &loc+2 + ROTL4CONT &loc,&n-16 + mexit +.skip6 + ldx &loc+1 + lda &loc+3 + ora &loc-1 + sta &loc+2 + stx &loc + ROTR4CONT &loc,24-&n + mend + + +* This makes a function wrapper that is callable from C, +* taking a pointer to the context structure as its argument. + macro + CFunction &fn + phb + plx + ply + tdc + pld + plb + plb + phy + phx + plb + pha + jsl &fn + pld + rtl + mend + + +* One iteration of the loop for processing blocks. +* The a,b,c,d variables are given as parameters so we can avoid cycling them. +* shift is a per-round shift amount. + macro + BlockLoopIter &a,&b,&c,&d,&shift + +* f_0 to f_15 + aif &part<>1,.skip1 + lda &c + eor &d + and &b + eor &d + clc + adc &a + sta temp + + lda &c+2 + eor &d+2 + and &b+2 + eor &d+2 + adc &a+2 + sta temp+2 +.skip1 + +* f_16 to f_31 + aif &part<>2,.skip2 + lda &c + tax + ora &d + and &b + sta temp + txa + and &d + ora temp + clc + adc &a + tay + + lda &c+2 + tax + ora &d+2 + and &b+2 + sta temp+2 + txa + and &d+2 + ora temp+2 + adc &a+2 + tax + + clc + tya + adc #$7999 + sta temp + txa + adc #$5A82 + sta temp+2 +.skip2 + +* f_32 to f_47 + aif &part<>3,.skip3 + lda &b + eor &c + eor &d + clc + adc &a + tay + + lda &b+2 + eor &c+2 + eor &d+2 + adc &a+2 + tax + + clc + tya + adc #$EBA1 + sta temp + txa + adc #$6ED9 + sta temp+2 +.skip3 + + ldy idx + ldx g_times_4,y + lda m,x + clc + adc temp + sta temp + inx + inx + lda m,x + adc temp+2 + sta temp+2 + + iny + iny + sty idx + + ROTL4AUTO temp,&shift,1 + + lda temp + sta &a + lda temp+2 + sta &a+2 + + mend + + +* One part of the loop for processing blocks (16 iterations) + macro + BlockLoopPart &part + +loop&part anop + + aif &part<>1,.skip1a + BlockLoopIter a_,b,c,d,3 + BlockLoopIter d,a_,b,c,7 + BlockLoopIter c,d,a_,b,11 + BlockLoopIter b,c,d,a_,19 +.skip1a + aif &part<>2,.skip2a + BlockLoopIter a_,b,c,d,3 + BlockLoopIter d,a_,b,c,5 + BlockLoopIter c,d,a_,b,9 + BlockLoopIter b,c,d,a_,13 +.skip2a + aif &part<>3,.skip3a + BlockLoopIter a_,b,c,d,3 + BlockLoopIter d,a_,b,c,9 + BlockLoopIter c,d,a_,b,11 + BlockLoopIter b,c,d,a_,15 +.skip3a + + lda idx + cmp #16*2*&part + bge endloop&part + jmp loop&part +endloop&part anop + mend + diff --git a/md4sum.c b/md4sum.c new file mode 100644 index 0000000..6f923ac --- /dev/null +++ b/md4sum.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017,2023 Stephen Heumann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "md4.h" +#define HASH_FUNCTION md4 +#include "cksumcommon.h" + diff --git a/md4test.c b/md4test.c new file mode 100644 index 0000000..24816e5 --- /dev/null +++ b/md4test.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017,2023 Stephen Heumann + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "md4.h" +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + unsigned int i; + unsigned long tick_count; + long double bytes_per_sec; + + struct md4_context *context, **context_hndl; + struct md4_context context_init = {0,0,0, {0}, {0}, {0}, + {0x61,0x62,0x63,0x80, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 + }}; + + context_hndl = (struct md4_context **)NewHandle(sizeof(struct md4_context), + userid(), attrFixed|attrPage|attrBank|attrNoCross, 0x000000); + if (toolerror()) + return 0; + context = *context_hndl; + *context = context_init; + + md4_init(context); + md4_processblock(context); + + printf("h[..] = %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", + context->hash[0], context->hash[1], context->hash[2], context->hash[3], + context->hash[4], context->hash[5], context->hash[6], context->hash[7], + context->hash[8], context->hash[9], context->hash[10], context->hash[11], + context->hash[12], context->hash[13], context->hash[14], context->hash[15]); + + tick_count = GetTick(); + for (i = 0; i < 1000; i++) { + md4_processblock(context); + } + tick_count = GetTick() - tick_count; + + bytes_per_sec = (long double)1000 * 64 * 60 / tick_count; + printf("Time for 1000 iters = %lu ticks (%lf bytes/sec)\n", tick_count, bytes_per_sec); + + tick_count = GetTick(); + md4_init(context); + md4_update(context, (void*)0x030000, 64000); + md4_finalize(context); + tick_count = GetTick() - tick_count; + bytes_per_sec = (long double)1000 * 64 * 60 / tick_count; + printf("Append time = %lu ticks (%lf bytes/sec)\n", tick_count, bytes_per_sec); + + if (argc > 1) { + md4_init(context); + md4_update(context, argv[1], strlen(argv[1])); + md4_finalize(context); + + printf("h[..] = %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", + context->hash[0], context->hash[1], context->hash[2], context->hash[3], + context->hash[4], context->hash[5], context->hash[6], context->hash[7], + context->hash[8], context->hash[9], context->hash[10], context->hash[11], + context->hash[12], context->hash[13], context->hash[14], context->hash[15]); + } + +}