HASHTOOL!' @[TOOL128.ASM9p\BUILDTOOL128 FINDER.DATA p!.TOOL128.MACS.S  VHASH.H&7\M16.HASHTOOL $8 \TOOL128.DOCSP2$* xET! | keep tool128 mcopy tool128.macros ;Orca Macros ************************************************************** * * Hash Tool * * * Reference: Apple IIGS Toolbox Reference, Volume 2, Appendix A * **************************************************************** * * September 1999 -- version 1.0 released. * Only md5 available. * * July 2002 -- version 1.0.1 released. * Andrew's md4 routines added. * * June 2004 -- version 1.0.2 release. * >0>t  ~(EE  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'q0*5 TOOL128.DOCS5B TOOL128.ASMD BUILDTOOL1285TOOL128.MACS.SHASH.H M16.HASHTOOL Fixed memory corruption bug in md4 and md5 if * DBR != PBR. * **************************************************************** ; ; md5 code is a port of md5 written by L. Peter Deutsch, ghost@aladdin.com ; ;Comments from Andrew: ; [md4 code] created by Andrew Roughan 30 June 2002 ; Geoff's md5 implementation was based on L. Peter Deutsch's md5.c ; As md4 and md5 are very similar, I set out to find a way to reuse ; what Geoff had done to create an md4 toolset. ; L. Peter Deutsch does not appear to have implemented md4, so ; I went back to RFC1320 and created C source code for md4 in the style ; that L.Peter Deutsch may have done if he had been inclined. ; By comparing my C code for md4 (in Peter's style) with Peter's C code ; for md5 and looking at Geoff's implementation of md5 as a toolset, ; I was able to easily see where Geoff's code could be reused and ; where modifications were necessary to create md4 subroutines. ; ;............................................................... ; ; Written by Geoff Weiss, geoff@apple2.gs ; ; Copyleft 1999 by Geoff Weiss, geoff@apple2.gs ; ; This source code may only be distributed on A2central, hashtool.gwlink.net ; web site, disks provided by Shareware Solutions II and Juiced.GS, and any ; mailing list run by Geoff Weiss. Any other distribution is prohibited ; and so by deemed illegal. If none of these distribution points are ; available, the code may be distributed anywhere. ; ; Binaries may be distributed by the following methods: ; (source must be provided with binaries) ; A2central libraries ; Shareware Solutions II and Juiced.GS disk collections ; mailing lists run by Geoff Weiss ; Any 3rd party software which requires use of this software. ; ; Prosecution of violators will strictly follow all national and local ; laws. ; ; To avoid incompatible versions of the software to be distributed, it ; is recommended to let Geoff Weiss run a CVS repository for development. ; ;............................................................... ; ; GNU GENERAL PUBLIC LICENSE ; TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ; ; 0. This License applies to any program or other work which contains ;a notice placed by the copyright holder saying it may be distributed ;under the terms of this General Public License. The "Program", below, ;refers to any such program or work, and a "work based on the Program" ;means either the Program or any derivative work under copyright law: ;that is to say, a work containing the Program or a portion of it, ;either verbatim or with modifications and/or translated into another ;language. (Hereinafter, translation is included without limitation in ;the term "modification".) Each licensee is addressed as "you". ; ;Activities other than copying, distribution and modification are not ;covered by this License; they are outside its scope. The act of ;running the Program is not restricted, and the output from the Program ;is covered only if its contents constitute a work based on the ;Program (independent of having been made by running the Program). ;Whether that is true depends on what the Program does. ; ; 1. You may copy and distribute verbatim copies of the Program's ;source code as you receive it, in any medium, provided that you ;conspicuously and appropriately publish on each copy an appropriate ;copyright notice and disclaimer of warranty; keep intact all the ;notices that refer to this License and to the absence of any warranty; ;and give any other recipients of the Program a copy of this License ;along with the Program. ; ;You may charge a fee for the physical act of transferring a copy, and ;you may at your option offer warranty protection in exchange for a fee. ; ; 2. You may modify your copy or copies of the Program or any portion ;of it, thus forming a work based on the Program, and copy and ;distribute such modifications or work under the terms of Section 1 ;above, provided that you also meet all of these conditions: ; ; a) You must cause the modified files to carry prominent notices ; stating that you changed the files and the date of any change. ; ; b) You must cause any work that you distribute or publish, that in ; whole or in part contains or is derived from the Program or any ; part thereof, to be licensed as a whole at no charge to all third ; parties under the terms of this License. ; ; c) If the modified program normally reads commands interactively ; when run, you must cause it, when started running for such ; interactive use in the most ordinary way, to print or display an ; announcement including an appropriate copyright notice and a ; notice that there is no warranty (or else, saying that you provide ; a warranty) and that users may redistribute the program under ; these conditions, and telling the user how to view a copy of this ; License. (Exception: if the Program itself is interactive but ; does not normally print such an announcement, your work based on ; the Program is not required to print an announcement.) ; ;These requirements apply to the modified work as a whole. If ;identifiable sections of that work are not derived from the Program, ;and can be reasonably considered independent and separate works in ;themselves, then this License, and its terms, do not apply to those ;sections when you distribute them as separate works. But when you ;distribute the same sections as part of a whole which is a work based ;on the Program, the distribution of the whole must be on the terms of ;this License, whose permissions for other licensees extend to the ;entire whole, and thus to each and every part regardless of who wrote it. ; ;Thus, it is not the intent of this section to claim rights or contest ;your rights to work written entirely by you; rather, the intent is to ;exercise the right to control the distribution of derivative or ;collective works based on the Program. ; ;In addition, mere aggregation of another work not based on the Program ;with the Program (or with a work based on the Program) on a volume of ;a storage or distribution medium does not bring the other work under ;the scope of this License. ; ; 3. You may copy and distribute the Program (or a work based on it, ;under Section 2) in object code or executable form under the terms of ;Sections 1 and 2 above provided that you also do one of the following: ; ; a) Accompany it with the complete corresponding machine-readable ; source code, which must be distributed under the terms of Sections ; 1 and 2 above on a medium customarily used for software interchange; or, ; ; b) Accompany it with a written offer, valid for at least three ; years, to give any third party, for a charge no more than your ; cost of physically performing source distribution, a complete ; machine-readable copy of the corresponding source code, to be ; distributed under the terms of Sections 1 and 2 above on a medium ; customarily used for software interchange; or, ; ; c) Accompany it with the information you received as to the offer ; to distribute corresponding source code. (This alternative is ; allowed only for noncommercial distribution and only if you ; received the program in object code or executable form with such ; an offer, in accord with Subsection b above.) ; ;The source code for a work means the preferred form of the work for ;making modifications to it. For an executable work, complete source ;code means all the source code for all modules it contains, plus any ;associated interface definition files, plus the scripts used to ;control compilation and installation of the executable. However, as a ;special exception, the source code distributed need not include ;anything that is normally distributed (in either source or binary ;form) with the major components (compiler, kernel, and so on) of the ;operating system on which the executable runs, unless that component ;itself accompanies the executable. ; ;If distribution of executable or object code is made by offering ;access to copy from a designated place, then offering equivalent ;access to copy the source code from the same place counts as ;distribution of the source code, even though third parties are not ;compelled to copy the source along with the object code. ; ; 4. You may not copy, modify, sublicense, or distribute the Program ;except as expressly provided under this License. Any attempt ;otherwise to copy, modify, sublicense or distribute the Program is ;void, and will automatically terminate your rights under this License. ;However, parties who have received copies, or rights, from you under ;this License will not have their licenses terminated so long as such ;parties remain in full compliance. ; ; 5. You are not required to accept this License, since you have not ;signed it. However, nothing else grants you permission to modify or ;distribute the Program or its derivative works. These actions are ;prohibited by law if you do not accept this License. Therefore, by ;modifying or distributing the Program (or any work based on the ;Program), you indicate your acceptance of this License to do so, and ;all its terms and conditions for copying, distributing or modifying ;the Program or works based on it. ; ; 6. Each time you redistribute the Program (or any work based on the ;Program), the recipient automatically receives a license from the ;original licensor to copy, distribute or modify the Program subject to ;these terms and conditions. You may not impose any further ;restrictions on the recipients' exercise of the rights granted herein. ;You are not responsible for enforcing compliance by third parties to ;this License. ; ; 7. If, as a consequence of a court judgment or allegation of patent ;infringement or for any other reason (not limited to patent issues), ;conditions are imposed on you (whether by court order, agreement or ;otherwise) that contradict the conditions of this License, they do not ;excuse you from the conditions of this License. If you cannot ;distribute so as to satisfy simultaneously your obligations under this ;License and any other pertinent obligations, then as a consequence you ;may not distribute the Program at all. For example, if a patent ;license would not permit royalty-free redistribution of the Program by ;all those who receive copies directly or indirectly through you, then ;the only way you could satisfy both it and this License would be to ;refrain entirely from distribution of the Program. ; ;If any portion of this section is held invalid or unenforceable under ;any particular circumstance, the balance of the section is intended to ;apply and the section as a whole is intended to apply in other ;circumstances. ; ;It is not the purpose of this section to induce you to infringe any ;patents or other property right claims or to contest validity of any ;such claims; this section has the sole purpose of protecting the ;integrity of the free software distribution system, which is ;implemented by public license practices. Many people have made ;generous contributions to the wide range of software distributed ;through that system in reliance on consistent application of that ;system; it is up to the author/donor to decide if he or she is willing ;to distribute software through any other system and a licensee cannot ;impose that choice. ; ;This section is intended to make thoroughly clear what is believed to ;be a consequence of the rest of this License. ; ; 8. If the distribution and/or use of the Program is restricted in ;certain countries either by patents or by copyrighted interfaces, the ;original copyright holder who places the Program under this License ;may add an explicit geographical distribution limitation excluding ;those countries, so that distribution is permitted only in or among ;countries not thus excluded. In such case, this License incorporates ;the limitation as if written in the body of this License. ; ; 9. The Free Software Foundation may publish revised and/or new versions ;of the General Public License from time to time. Such new versions will ;be similar in spirit to the present version, but may differ in detail to ;address new problems or concerns. ; ;Each version is given a distinguishing version number. If the Program ;specifies a version number of this License which applies to it and "any ;later version", you have the option of following the terms and conditions ;either of that version or of any later version published by the Free ;Software Foundation. If the Program does not specify a version number of ;this License, you may choose any version ever published by the Free Software ;Foundation. ; ; 10. If you wish to incorporate parts of the Program into other free ;programs whose distribution conditions are different, write to the author ;to ask for permission. For software which is copyrighted by the Free ;Software Foundation, write to the Free Software Foundation; we sometimes ;make exceptions for this. Our decision will be guided by the two goals ;of preserving the free status of all derivatives of our free software and ;of promoting the sharing and reuse of software generally. ; ; NO WARRANTY ; ; 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ;FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ;OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ;PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ;OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ;MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ;TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ;PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ;REPAIR OR CORRECTION. ; ; 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ;WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ;REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ;INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ;OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ;TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ;YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ;PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ;POSSIBILITY OF SUCH DAMAGES. ; ; END OF TERMS AND CONDITIONS **************************************************************** * * Function Pointer Table (FPT) * * This table is required by the Tool Locator. It must be at * the start of the file. * **************************************************************** * * case on * state struct parameters count gequ 0 count0 gequ 0 count1 gequ 4 abcd gequ 8 abcd0 gequ 8 abcd1 gequ 12 abcd2 gequ 16 abcd3 gequ 20 buf gequ 24 * T Computation T1 gequ $d76aa478 T2 gequ $e8c7b756 T3 gequ $242070db T4 gequ $c1bdceee T5 gequ $f57c0faf T6 gequ $4787c62a T7 gequ $a8304613 T8 gequ $fd469501 T9 gequ $698098d8 T10 gequ $8b44f7af T11 gequ $ffff5bb1 T12 gequ $895cd7be T13 gequ $6b901122 T14 gequ $fd987193 T15 gequ $a679438e T16 gequ $49b40821 T17 gequ $f61e2562 T18 gequ $c040b340 T19 gequ $265e5a51 T20 gequ $e9b6c7aa T21 gequ $d62f105d T22 gequ $02441453 T23 gequ $d8a1e681 T24 gequ $e7d3fbc8 T25 gequ $21e1cde6 T26 gequ $c33707d6 T27 gequ $f4d50d87 T28 gequ $455a14ed T29 gequ $a9e3e905 T30 gequ $fcefa3f8 T31 gequ $676f02d9 T32 gequ $8d2a4c8a T33 gequ $fffa3942 T34 gequ $8771f681 T35 gequ $6d9d6122 T36 gequ $fde5380c T37 gequ $a4beea44 T38 gequ $4bdecfa9 T39 gequ $f6bb4b60 T40 gequ $bebfbc70 T41 gequ $289b7ec6 T42 gequ $eaa127fa T43 gequ $d4ef3085 T44 gequ $04881d05 T45 gequ $d9d4d039 T46 gequ $e6db99e5 T47 gequ $1fa27cf8 T48 gequ $c4ac5665 T49 gequ $f4292244 T50 gequ $432aff97 T51 gequ $ab9423a7 T52 gequ $fc93a039 T53 gequ $655b59c3 T54 gequ $8f0ccc92 T55 gequ $ffeff47d T56 gequ $85845dd1 T57 gequ $6fa87e4f T58 gequ $fe2ce6e0 T59 gequ $a3014314 T60 gequ $4e0811a1 T61 gequ $f7537e82 T62 gequ $bd3af235 T63 gequ $2ad7d2bb T64 gequ $eb86d391 FPT data count equ 14 function number for the highest numbered ! tool call dc i4'count+1' number of routines + 1 dc a4'mdBootInit-1' required functions dc a4'mdStartUp-1' dc a4'mdShutDown-1' dc a4'mdVersion-1' dc a4'mdReset-1' dc a4'mdStatus-1' dc a4'Null-1' reserved functions dc a4'Null-1' dc a4'md5_init-1' user functions dc a4'md5_append-1' dc a4'md5_finish-1' dc a4'md4_init-1' dc a4'md4_append-1' dc a4'md4_finish-1' end **************************************************************** * * Common - common data * **************************************************************** * Common data ; ; Constants ; false equ 0 boolean constant true equ 1 boolean constant toolVersion equ $0102 tool version number 1.0.2 active dc i2'0' end **************************************************************** * * Null - Called for required tool functions that don't do * anything * * BootInit - Required function; called at boot or load time * Reset - Required function; called during a system reset * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * Null start mdBootInit entry mdReset entry clc no error lda #0 error code rtl end **************************************************************** * * Startup - Required function; called when the application * starts the tool * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * mdStartUp start using Common lda #true active = true sta >active clc no error lda #0 error code rtl end **************************************************************** * * Shutdown - Required function; called when the application * shuts down the tool * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * **************************************************************** * mdShutDown start using Common lda #false active = false sta >active clc no error lda #0 error code rtl end **************************************************************** * * Status - Required function; tells if the tool is active * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * toolStatus - true if the tool is started, else false * **************************************************************** * mdStatus start using Common toolStatus equ 7 stack offset for toolStatus return value lda >active toolStatus = status sta toolStatus,S clc no error lda #0 error code rtl end **************************************************************** * * Version - Required function; returns the tool version * * Outputs: * C - clear, indicating no error * A - 0, indicating no error * outVersion - tool version number * **************************************************************** * mdVersion start using Common RTL1 equ 1 RTL2 equ RTL1+3 outVersion equ RTL2+3 stack offset for version return value lda #toolVersion version = toolVersion sta outVersion,S clc no error lda #0 error code rtl end md5_init start md4_init entry Using Common directPageOnStack equ 2 ; number of bytes from a phd ; state pointer - 4 bytes ; RTL2 - 3 bytes ; RTL1 - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 state equ RTL2+3 outputSpace equ state+4 (if there was a return value) inputsize equ outputSpace-state phd set up our direct page tsc tcd lda >active jeq clean_up lda #0 sta [state] ldy #count0+2 sta [state],y ldy #count1 sta [state],y ldy #count1+2 sta [state],y ldy #abcd0 lda #$2301 sta [state],y ldy #abcd0+2 lda #$6745 sta [state],y ldy #abcd1 lda #$ab89 sta [state],y ldy #abcd1+2 lda #$efcd sta [state],y ldy #abcd2 lda #$dcfe sta [state],y ldy #abcd2+2 lda #$98ba sta [state],y ldy #abcd3 lda #$5476 sta [state],y ldy #abcd3+2 lda #$1032 sta [state],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end md5_append start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 nbytes equ RTL2+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes phd set up our direct page tsc tcd lda >active jeq clean_up pei pms+2 pei pms pei data+2 pei data pei nbytes+2 pei nbytes jsl >md5_append2 clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end md5_append2 start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes p equ 1 dpEnd equ p+4 RTL equ dpEnd+directPageOnStack nbytes equ RTL+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes dpsize equ dpEnd-p phd set up our direct page tsc sec sbc #dpsize tcs tcd ; if (nbytes <= 0) return; lda nbytes+2 jmi clean_up ora nbytes jeq clean_up ; *p = data; lda data sta p lda data+2 sta p+2 ; left = nbytes lda nbytes sta >left lda nbytes+2 sta >left+2 ; offset = (pms->count[0] >> 3) & 63; ldy #count0+2 lda [pms],y lsr a sta >temp lda [pms] ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a and #63 sta >offset ; nbits = nbytes << 3; lda nbytes asl a sta >nbits lda nbytes+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 ; pms->count[1] += nbytes >> 29; lda nbytes+2 lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a clc ldy #count1 adc [pms],y sta [pms],y lda #0 ldy #count1+2 adc [pms],y sta [pms],y ; pms->count[0] += nbits; lda [pms] clc adc >nbits sta [pms] ldy #count0+2 lda [pms],y adc >nbits+2 sta [pms],y ; if (pms->count[0] < nbits) ldy #count0+2 lda [pms],y cmp >nbits+2 bcc do_if_true_1 beq do_check_lsw_1 bcs process1stBlock do_check_lsw_1 anop lda [pms] cmp >nbits bcs process1stBlock do_if_true_1 anop ; pms->count[1]++; ldy #count1 lda [pms],y clc adc #1 sta [pms],y ldy #count1+2 lda [pms],y adc #0 sta [pms],y process1stBlock anop ; if (offset) lda >offset jeq processFullBlock ; copy = (offset + nbytes > 64 ? 64 - offset : nbytes; lda >offset clc adc nbytes sta >temp lda #0 adc nbytes+2 bne ternary_true_1 lda >temp cmp #65 bcc ternary_false_1 ternary_true_1 anop lda #64 sec sbc >offset sta >copy lda #0 sta >copy+2 bra ternary_done_1 ternary_false_1 anop lda nbytes sta >copy lda nbytes+2 sta >copy+2 ternary_done_1 anop ; memcpy(pms->buf+offset,p , copy); pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 sta >temp txa clc adc >offset tax lda >temp clc adc #0 pha phx lda >copy+2 pha lda >copy pha ldx #$2b02 _BlockMove jsl >$e10000 ; if (offset + copy < 64) return; lda >offset clc adc >copy sta >temp lda #0 adc >copy+2 bne do_if_false_2 lda >temp cmp #64 bcs do_if_false_2 brl clean_up do_if_false_2 anop ; p+= copy; lda p clc adc >copy sta p lda p+2 adc >copy+2 sta p+2 ; left-=copy; lda >left sec sbc >copy sta >left lda >left+2 sbc >copy+2 sta >left+2 ; md5_process(pms,pms->buf); pei pms+2 pei pms lda pms clc adc #buf tax lda pms+2 adc #0 pha phx jsl >md5_process processFullBlock anop ; for (; left >= 64; p+=64, left -= 64) md5_process(pms,p); lda >left+2 bne in_forloop_1 lda >left cmp #64 jcc processFinalBlock in_forloop_1 anop pei pms+2 pei pms pei p+2 pei p jsl >md5_process lda p clc adc #64 sta p lda p+2 adc #0 sta p+2 lda >left sec sbc #64 sta >left lda >left+2 sbc #0 sta >left+2 bra processFullBlock processFinalBlock anop ; if (left) memcpy(pms->buf,p,left); lda >left ora >left+2 beq clean_up pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 pha phx lda >left+2 pha lda >left pha ldx #$2b02 _BlockMove jsl >$e10000 clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? ; adc #inputsize tcs rtl temp ds 2 left ds 4 offset ds 2 nbits ds 4 copy ds 4 end md5_process start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes dpStart equ 1 X equ dpStart dpEnd equ X+4 RTL equ dpEnd+directPageOnStack data equ RTL+3 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-data dpsize equ dpEnd-dpStart phd set up our direct page tsc sec sbc #dpsize tcd tcs ; a=pms->abcd[0]; b=pms->abcd[1]; c=pms->abcd[2]; d=pms->abcd[3] ldy #abcd0 lda [pms],y sta >a_ ldy #abcd0+2 lda [pms],y sta >a_+2 ldy #abcd1 lda [pms],y sta >b_ ldy #abcd1+2 lda [pms],y sta >b_+2 ldy #abcd2 lda [pms],y sta >c_ ldy #abcd2+2 lda [pms],y sta >c_+2 ldy #abcd3 lda [pms],y sta >d_ ldy #abcd3+2 lda [pms],y sta >d_+2 ; X = data lda data sta X lda data+2 sta X+2 ; round 1 ; SET(a, b, c, d, 0, 7, T1); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 7 pea T1|-$10 pea T1 jsr md5_set ; SET(d, a, b, c, 1, 12, T2); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 1 pea 12 pea T2|-$10 pea T2 jsr md5_set ; SET(c, d, a, b, 2, 17, T3); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 17 pea T3|-$10 pea T3 jsr md5_set ; SET(b, c, d, a, 3, 22, T4); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 3 pea 22 pea T4|-$10 pea T4 jsr md5_set ; SET(a, b, c, d, 4, 7, T5); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 7 pea T5|-$10 pea T5 jsr md5_set ; SET(d, a, b, c, 5, 12, T6); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 12 pea T6|-$10 pea T6 jsr md5_set ; SET(c, d, a, b, 6, 17, T7); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 17 pea T7|-$10 pea T7 jsr md5_set ; SET(b, c, d, a, 7, 22, T8); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 7 pea 22 pea T8|-$10 pea T8 jsr md5_set ; SET(a, b, c, d, 8, 7, T9); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 7 pea T9|-$10 pea T9 jsr md5_set ; SET(d, a, b, c, 9, 12, T10); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 12 pea T10|-$10 pea T10 jsr md5_set ; SET(c, d, a, b, 10, 17, T11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 17 pea T11|-$10 pea T11 jsr md5_set ; SET(b, c, d, a, 11, 22, T12); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 11 pea 22 pea T12|-$10 pea T12 jsr md5_set ; SET(a, b, c, d, 12, 7, T13); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 7 pea T13|-$10 pea T13 jsr md5_set ; SET(d, a, b, c, 13, 12, T14); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 13 pea 12 pea T14|-$10 pea T14 jsr md5_set ; SET(c, d, a, b, 14, 17, T15); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 17 pea T15|-$10 pea T15 jsr md5_set ; SET(b, c, d, a, 15, 22, T16); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 22 pea T16|-$10 pea T16 jsr md5_set ; round2 ; SET(a, b, c, d, 1, 5, T17); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 5 pea T17|-$10 pea T17 jsr md5_set2 ; SET(d, a, b, c, 6, 9, T18); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 6 pea 9 pea T18|-$10 pea T18 jsr md5_set2 ; SET(c, d, a, b, 11, 14, T19); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 14 pea T19|-$10 pea T19 jsr md5_set2 ; SET(b, c, d, a, 0, 20, T20); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 0 pea 20 pea T20|-$10 pea T20 jsr md5_set2 ; SET(a, b, c, d, 5, 5, T21); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 5 pea 5 pea T21|-$10 pea T21 jsr md5_set2 ; SET(d, a, b, c, 10, 9, T22); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 10 pea 9 pea T22|-$10 pea T22 jsr md5_set2 ; SET(c, d, a, b, 15, 14, T23); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 15 pea 14 pea T23|-$10 pea T23 jsr md5_set2 ; SET(b, c, d, a, 4, 20, T24); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 4 pea 20 pea T24|-$10 pea T24 jsr md5_set2 ; SET(a, b, c, d, 9, 5, T25); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 9 pea 5 pea T25|-$10 pea T25 jsr md5_set2 ; SET(d, a, b, c, 14, 9, T26); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 14 pea 9 pea T26|-$10 pea T26 jsr md5_set2 ; SET(c, d, a, b, 3, 14, T27); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 3 pea 14 pea T27|-$10 pea T27 jsr md5_set2 ; SET(b, c, d, a, 8, 20, T28); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 8 pea 20 pea T28|-$10 pea T28 jsr md5_set2 ; SET(a, b, c, d, 13, 5, T29); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 13 pea 5 pea T29|-$10 pea T29 jsr md5_set2 ; SET(d, a, b, c, 2, 9, T30); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 2 pea 9 pea T30|-$10 pea T30 jsr md5_set2 ; SET(c, d, a, b, 7, 14, T31); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 14 pea T31|-$10 pea T31 jsr md5_set2 ; SET(b, c, d, a, 12, 20, T32); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 20 pea T32|-$10 pea T32 jsr md5_set2 ; round3 ; SET(a, b, c, d, 5, 4, T33); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 5 pea 4 pea T33|-$10 pea T33 jsr md5_set3 ; SET(d, a, b, c, 8, 11, T34); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 8 pea 11 pea T34|-$10 pea T34 jsr md5_set3 ; SET(c, d, a, b, 11, 16, T35); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 16 pea T35|-$10 pea T35 jsr md5_set3 ; SET(b, c, d, a, 14, 23, T36); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 23 pea T36|-$10 pea T36 jsr md5_set3 ; SET(a, b, c, d, 1, 4, T37); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 4 pea T37|-$10 pea T37 jsr md5_set3 ; SET(d, a, b, c, 4, 11, T38); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 4 pea 11 pea T38|-$10 pea T38 jsr md5_set3 ; SET(c, d, a, b, 7, 16, T39); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 16 pea T39|-$10 pea T39 jsr md5_set3 ; SET(b, c, d, a, 10, 23, T40); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 10 pea 23 pea T40|-$10 pea T40 jsr md5_set3 ; SET(a, b, c, d, 13, 4, T41); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 13 pea 4 pea T41|-$10 pea T41 jsr md5_set3 ; SET(d, a, b, c, 0, 11, T42); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 0 pea 11 pea T42|-$10 pea T42 jsr md5_set3 ; SET(c, d, a, b, 3, 16, T43); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 3 pea 16 pea T43|-$10 pea T43 jsr md5_set3 ; SET(b, c, d, a, 6, 23, T44); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 6 pea 23 pea T44|-$10 pea T44 jsr md5_set3 ; SET(a, b, c, d, 9, 4, T45); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 9 pea 4 pea T45|-$10 pea T45 jsr md5_set3 ; SET(d, a, b, c, 12, 11, T46); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 12 pea 11 pea T46|-$10 pea T46 jsr md5_set3 ; SET(c, d, a, b, 15, 16, T47); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 15 pea 16 pea T47|-$10 pea T47 jsr md5_set3 ; SET(b, c, d, a, 2, 23, T48); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 2 pea 23 pea T48|-$10 pea T48 jsr md5_set3 ; round4 ; SET(a, b, c, d, 0, 6, T49); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 6 pea T49|-$10 pea T49 jsr md5_set4 ; SET(d, a, b, c, 7, 10, T50); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 7 pea 10 pea T50|-$10 pea T50 jsr md5_set4 ; SET(c, d, a, b, 14, 15, T51); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 15 pea T51|-$10 pea T51 jsr md5_set4 ; SET(b, c, d, a, 5, 21, T52); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 5 pea 21 pea T52|-$10 pea T52 jsr md5_set4 ; SET(a, b, c, d, 12, 6, T53); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 6 pea T53|-$10 pea T53 jsr md5_set4 ; SET(d, a, b, c, 3, 10, T54); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 3 pea 10 pea T54|-$10 pea T54 jsr md5_set4 ; SET(c, d, a, b, 10, 15, T55); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 15 pea T55|-$10 pea T55 jsr md5_set4 ; SET(b, c, d, a, 1, 21, T56); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 1 pea 21 pea T56|-$10 pea T56 jsr md5_set4 ; SET(a, b, c, d, 8, 6, T57); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 6 pea T57|-$10 pea T57 jsr md5_set4 ; SET(d, a, b, c, 15, 10, T58); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 15 pea 10 pea T58|-$10 pea T58 jsr md5_set4 ; SET(c, d, a, b, 6, 15, T59); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 15 pea T59|-$10 pea T59 jsr md5_set4 ; SET(b, c, d, a, 13, 21, T60); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 21 pea T60|-$10 pea T60 jsr md5_set4 ; SET(a, b, c, d, 4, 6, T61); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 6 pea T61|-$10 pea T61 jsr md5_set4 ; SET(d, a, b, c, 11, 10, T62); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 11 pea 10 pea T62|-$10 pea T62 jsr md5_set4 ; SET(c, d, a, b, 2, 15, T63); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 15 pea T63|-$10 pea T63 jsr md5_set4 ; SET(b, c, d, a, 9, 21, T64); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 9 pea 21 pea T64|-$10 pea T64 jsr md5_set4 ; pms->abcd[0] += a; ldy #abcd0 lda [pms],y clc adc >a_ sta [pms],y ldy #abcd0+2 lda [pms],y adc >a_+2 sta [pms],y ; pms->abcd[1] += b; ldy #abcd1 lda [pms],y clc adc >b_ sta [pms],y ldy #abcd1+2 lda [pms],y adc >b_+2 sta [pms],y ; pms->abcd[2] += c; ldy #abcd2 lda [pms],y clc adc >c_ sta [pms],y ldy #abcd2+2 lda [pms],y adc >c_+2 sta [pms],y ; pms->abcd[3] += d; ldy #abcd3 lda [pms],y clc adc >d_ sta [pms],y ldy #abcd3+2 lda [pms],y adc >d_+2 sta [pms],y clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? tcs rtl md5_set anop set_phd equ 1 set_rts equ set_phd+2 set_t equ set_rts+2 set_s equ set_t+4 set_k equ set_s+2 set_d equ set_k+2 set_c equ set_d+4 set_b equ set_c+4 set_a equ set_b+4 set_stackEnd equ set_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+F(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set_b+2 pei set_b pei set_c+2 pei set_c pei set_d+2 pei set_d jsr md5_f pla sta >t pla sta >t+2 lda set_k asl a ; multiply by 4 asl a tay lda [set_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set_t sta >t lda >t+2 adc set_t+2 sta >t+2 clc lda >t adc [set_a] sta >t lda >t+2 ldy #2 adc [set_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set_s jsr md5_rotate_left pla clc adc [set_b] sta [set_a] pla ldy #2 adc [set_b],y sta [set_a],y lda set_rts sta set_stackEnd-2 pld tsc clc adc #set_stackEnd-set_t tcs rts md5_set2 anop set2_phd equ 1 set2_rts equ set2_phd+2 set2_t equ set2_rts+2 set2_s equ set2_t+4 set2_k equ set2_s+2 set2_d equ set2_k+2 set2_c equ set2_d+4 set2_b equ set2_c+4 set2_a equ set2_b+4 set2_stackEnd equ set2_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+G(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set2_b+2 pei set2_b pei set2_c+2 pei set2_c pei set2_d+2 pei set2_d jsr md5_g pla sta >t pla sta >t+2 lda set2_k asl a ; multiply by 4 asl a tay lda [set2_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set2_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set2_t sta >t lda >t+2 adc set2_t+2 sta >t+2 clc lda >t adc [set2_a] sta >t lda >t+2 ldy #2 adc [set2_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set2_s jsr md5_rotate_left pla clc adc [set2_b] sta [set2_a] pla ldy #2 adc [set2_b],y sta [set2_a],y lda set2_rts sta set2_stackEnd-2 pld tsc clc adc #set2_stackEnd-set2_t tcs rts md5_set3 anop set3_phd equ 1 set3_rts equ set3_phd+2 set3_t equ set3_rts+2 set3_s equ set3_t+4 set3_k equ set3_s+2 set3_d equ set3_k+2 set3_c equ set3_d+4 set3_b equ set3_c+4 set3_a equ set3_b+4 set3_stackEnd equ set3_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+H(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set3_b+2 pei set3_b pei set3_c+2 pei set3_c pei set3_d+2 pei set3_d jsr md5_h pla sta >t pla sta >t+2 lda set3_k asl a ; multiply by 4 asl a tay lda [set3_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set3_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set3_t sta >t lda >t+2 adc set3_t+2 sta >t+2 clc lda >t adc [set3_a] sta >t lda >t+2 ldy #2 adc [set3_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set3_s jsr md5_rotate_left pla clc adc [set3_b] sta [set3_a] pla ldy #2 adc [set3_b],y sta [set3_a],y lda set3_rts sta set3_stackEnd-2 pld tsc clc adc #set3_stackEnd-set3_t tcs rts md5_set4 anop set4_phd equ 1 set4_rts equ set4_phd+2 set4_t equ set4_rts+2 set4_s equ set4_t+4 set4_k equ set4_s+2 set4_d equ set4_k+2 set4_c equ set4_d+4 set4_b equ set4_c+4 set4_a equ set4_b+4 set4_stackEnd equ set4_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s,Ti) t=a+I(b,c,d)+X[k]+T1 a=ROTATE_LEFT(t,s)+b pha ; space for return value pha pei set4_b+2 pei set4_b pei set4_c+2 pei set4_c pei set4_d+2 pei set4_d jsr md5_i pla sta >t pla sta >t+2 lda set4_k asl a ; multiply by 4 asl a tay lda [set4_stackEnd+X-1],y ; access X in direct page from clc ; routine calling this one adc >t sta >t iny iny lda [set4_stackEnd+X-1],y adc >t+2 sta >t+2 clc lda >t adc set4_t sta >t lda >t+2 adc set4_t+2 sta >t+2 clc lda >t adc [set4_a] sta >t lda >t+2 ldy #2 adc [set4_a],y sta >t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei set4_s jsr md5_rotate_left pla clc adc [set4_b] sta [set4_a] pla ldy #2 adc [set4_b],y sta [set4_a],y lda set4_rts sta set4_stackEnd-2 pld tsc clc adc #set4_stackEnd-set4_t tcs rts md5_f entry f_phd equ 1 f_rts equ f_phd+2 f_z equ f_rts+2 f_y equ f_z+4 f_x equ f_y+4 f_return equ f_x+4 f_stackEnd equ f_return+4 phd tsc tcd ; #define F(x,y,z) (((x) & (y)) | (~(x) & (z))) lda [f_x] and [f_y] tax ldy #2 lda [f_x],y and [f_y],y sta f_y+2 txa sta f_y lda [f_x] eor #$ffff and [f_z] ora f_y sta f_return lda [f_x],y eor #$ffff and [f_z],y ora f_y+2 sta f_return+2 lda f_rts sta f_return-2 pld tsc clc adc #f_return-f_z tcs rts md5_g anop g_phd equ 1 g_rts equ g_phd+2 g_z equ g_rts+2 g_y equ g_z+4 g_x equ g_y+4 g_return equ g_x+4 g_stackEnd equ g_return+4 phd tsc tcd ; #define G(x,y,z) (((x) & (z)) | ((y) & ~(z))) lda [g_x] and [g_z] tax ldy #2 lda [g_x],y and [g_z],y sta g_x+2 txa sta g_x lda [g_z] eor #$ffff and [g_y] ora g_x sta g_return lda [g_z],y eor #$ffff and [g_y],y ora g_x+2 sta g_return+2 lda g_rts sta g_return-2 pld tsc clc adc #g_return-g_z tcs rts md5_h entry h_phd equ 1 h_rts equ h_phd+2 h_z equ h_rts+2 h_y equ h_z+4 h_x equ h_y+4 h_return equ h_x+4 h_stackEnd equ h_return+4 phd tsc tcd ; #define H(x,y,z) ((x) ^ (y) ^ (z)) lda [h_x] eor [h_y] eor [h_z] sta h_return ldy #2 lda [h_x],y eor [h_y],y eor [h_z],y sta h_return+2 lda h_rts sta h_return-2 pld tsc clc adc #h_return-h_z tcs rts md5_i anop i_phd equ 1 i_rts equ i_phd+2 i_z equ i_rts+2 i_y equ i_z+4 i_x equ i_y+4 i_return equ i_x+4 i_stackEnd equ i_return+4 phd tsc tcd ; #define I(x,y,z) ((y) ^ ((x) | ~(z))) lda [h_z] eor #$ffff ora [h_x] eor [h_y] sta h_return ldy #2 lda [h_z],y eor #$ffff ora [h_x],y eor [h_y],y sta h_return+2 lda h_rts sta h_return-2 pld tsc clc adc #h_return-h_z tcs rts md5_rotate_left entry rl_phd equ 1 rl_rts equ rl_phd+2 rl_n equ rl_rts+2 rl_x equ rl_n+2 rl_return equ rl_x+4 rl_stackEnd equ rl_return+4 phd tsc tcd ; #define ROTATE_LEFT(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) ldx rl_n rl_loop anop cpx #0 beq rl_loop_end lda rl_x asl a lda rl_x+2 rol a sta rl_x+2 lda rl_x rol a sta rl_x dex bra rl_loop rl_loop_end anop lda rl_x sta rl_return lda rl_x+2 sta rl_return+2 lda rl_rts sta rl_return-2 pld tsc clc adc #rl_return-rl_n tcs rts a_ ds 4 b_ ds 4 c_ ds 4 d_ ds 4 t ds 4 end md5_finish start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 digest equ RTL2+3 pms equ digest+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-digest phd set up our direct page tsc tcd lda >active jeq clean_up ; for (i=0; i < 8; ++i); ; data[i] = (pms->count[i >> 2] >> ((i & 3) << 3)); lda [pms] sta >data ldy #count0+2 lda [pms],y sta >data+2 ldy #count1 lda [pms],y sta >data+4 ldy #count1+2 lda [pms],y sta >data+6 ; md5_append(pms,pad, ((55 - (pms->count[0] >> 3)) & 63) +1); pei pms+2 pei pms pea pad|-$10 pea pad ldy #count0+2 lda [pms],y lsr a sta >temp+2 ldy #count0 lda [pms],y ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda #55 sec sbc >temp and #63 clc adc #1 pea 0 pha jsl >md5_append2 ; md5_append(pms, data, 8); pei pms+2 pei pms pea data|-$10 pea data pea 0 pea 8 jsl >md5_append2 ; for ( i = 0; i < 16; ++i); ; digest[i] = (pms->abcd[i >> 2] >> ((i & 3) << 3)) ldy #abcd0 lda [pms],y sta [digest] ldy #abcd0+2 lda [pms],y ldy #2 sta [digest],y ldy #abcd1 lda [pms],y ldy #4 sta [digest],y ldy #abcd1+2 lda [pms],y ldy #6 sta [digest],y ldy #abcd2 lda [pms],y ldy #8 sta [digest],y ldy #abcd2+2 lda [pms],y ldy #10 sta [digest],y ldy #abcd3 lda [pms],y ldy #12 sta [digest],y ldy #abcd3+2 lda [pms],y ldy #14 sta [digest],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl pad dc h'80' dc 63h'00' data ds 8 temp ds 4 end ; The only difference between md5_append and md4_append is the usage of ; the md4_append2 subroutine call. ; If you want to save code size, this can be optimized with a flag for ; md4 or md5. md4_append start Using Common directPageOnStack equ 2 ; number of bytes from a phd RTL1 equ 1+directPageOnStack RTL2 equ RTL1+3 nbytes equ RTL2+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes phd set up our direct page tsc tcd lda >active jeq clean_up pei pms+2 pei pms pei data+2 pei data pei nbytes+2 pei nbytes jsl >md4_append2 clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl end ; The only difference between md5_append2 and md4_append2 is the usage of ; the md4_process subroutine call. ; If you want to save code size, this can be optimized with a flag for ; md4 or md5. md4_append2 start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes p equ 1 dpEnd equ p+4 RTL equ dpEnd+directPageOnStack nbytes equ RTL+3 data equ nbytes+4 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-nbytes dpsize equ dpEnd-p phd set up our direct page tsc sec sbc #dpsize tcs tcd ; if (nbytes <= 0) return; lda nbytes+2 jmi clean_up ora nbytes jeq clean_up ; *p = data; lda data sta p lda data+2 sta p+2 ; left = nbytes lda nbytes sta >left lda nbytes+2 sta >left+2 ; offset = (pms->count[0] >> 3) & 63; ldy #count0+2 lda [pms],y lsr a sta >temp lda [pms] ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a sta >offset lda >temp lsr a sta >temp lda >offset ror a and #63 sta >offset ; nbits = nbytes << 3; lda nbytes asl a sta >nbits lda nbytes+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 lda >nbits asl a sta >nbits lda >nbits+2 rol a sta >nbits+2 ; pms->count[1] += nbytes >> 29; lda nbytes+2 lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a lsr a clc ldy #count1 adc [pms],y sta [pms],y lda #0 ldy #count1+2 adc [pms],y sta [pms],y ; pms->count[0] += nbits; lda [pms] clc adc >nbits sta [pms] ldy #count0+2 lda [pms],y adc >nbits+2 sta [pms],y ; if (pms->count[0] < nbits) ldy #count0+2 lda [pms],y cmp >nbits+2 bcc do_if_true_1 beq do_check_lsw_1 bcs process1stBlock do_check_lsw_1 anop lda [pms] cmp >nbits bcs process1stBlock do_if_true_1 anop ; pms->count[1]++; ldy #count1 lda [pms],y clc adc #1 sta [pms],y ldy #count1+2 lda [pms],y adc #0 sta [pms],y process1stBlock anop ; if (offset) lda >offset jeq processFullBlock ; copy = (offset + nbytes > 64 ? 64 - offset : nbytes; lda >offset clc adc nbytes sta >temp lda #0 adc nbytes+2 bne ternary_true_1 lda >temp cmp #65 bcc ternary_false_1 ternary_true_1 anop lda #64 sec sbc >offset sta >copy lda #0 sta >copy+2 bra ternary_done_1 ternary_false_1 anop lda nbytes sta >copy lda nbytes+2 sta >copy+2 ternary_done_1 anop ; memcpy(pms->buf+offset,p , copy); pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 sta >temp txa clc adc >offset tax lda >temp clc adc #0 pha phx lda >copy+2 pha lda >copy pha ldx #$2b02 _BlockMove jsl >$e10000 ; if (offset + copy < 64) return; lda >offset clc adc >copy sta >temp lda #0 adc >copy+2 bne do_if_false_2 lda >temp cmp #64 bcs do_if_false_2 brl clean_up do_if_false_2 anop ; p+= copy; lda p clc adc >copy sta p lda p+2 adc >copy+2 sta p+2 ; left-=copy; lda >left sec sbc >copy sta >left lda >left+2 sbc >copy+2 sta >left+2 ; md4_process(pms,pms->buf); pei pms+2 pei pms lda pms clc adc #buf tax lda pms+2 adc #0 pha phx jsl >md4_process processFullBlock anop ; for (; left >= 64; p+=64, left -= 64) md4_process(pms,p); lda >left+2 bne in_forloop_1 lda >left cmp #64 jcc processFinalBlock in_forloop_1 anop pei pms+2 pei pms pei p+2 pei p jsl >md4_process lda p clc adc #64 sta p lda p+2 adc #0 sta p+2 lda >left sec sbc #64 sta >left lda >left+2 sbc #0 sta >left+2 bra processFullBlock processFinalBlock anop ; if (left) memcpy(pms->buf,p,left); lda >left ora >left+2 beq clean_up pei p+2 pei p lda pms clc adc #buf tax lda pms+2 clc adc #0 pha phx lda >left+2 pha lda >left pha ldx #$2b02 _BlockMove jsl >$e10000 clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? ; adc #inputsize tcs rtl temp ds 2 left ds 4 offset ds 2 nbits ds 4 copy ds 4 end ; md4_process has quite significant changes from md5_process. md4_process start Using Common directPageOnStack equ 2 ; number of bytes from a phd ; pms pointer - 4 bytes ; data pointer - 4 bytes ; number bytes - 4 bytes ; RTL - 3 bytes ; <- SP before phd ; phd - 2 bytes ; <- SP after phd ; subroutine direct page space - 4 bytes dpStart equ 1 X equ dpStart dpEnd equ X+4 RTL equ dpEnd+directPageOnStack data equ RTL+3 pms equ data+4 outputSpace equ pms+4 (if there was a return value) inputsize equ outputSpace-data dpsize equ dpEnd-dpStart phd set up our direct page tsc sec sbc #dpsize tcd tcs ; This section of code is the same as the md5 section ; a=pms->abcd[0]; b=pms->abcd[1]; c=pms->abcd[2]; d=pms->abcd[3] ldy #abcd0 lda [pms],y sta >a_ ldy #abcd0+2 lda [pms],y sta >a_+2 ldy #abcd1 lda [pms],y sta >b_ ldy #abcd1+2 lda [pms],y sta >b_+2 ldy #abcd2 lda [pms],y sta >c_ ldy #abcd2+2 lda [pms],y sta >c_+2 ldy #abcd3 lda [pms],y sta >d_ ldy #abcd3+2 lda [pms],y sta >d_+2 ; X = data lda data sta X lda data+2 sta X+2 ; This is where md4_process diverges significantly from md5_process ; round 1 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set ; SET(d, a, b, c, 1, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 1 pea 7 jsr md4_set ; SET(c, d, a, b, 2, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 2 pea 11 jsr md4_set ; SET(b, c, d, a, 3, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 3 pea 19 jsr md4_set ; SET(a, b, c, d, 4, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 4 pea 3 jsr md4_set ; SET(d, a, b, c, 5, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 7 jsr md4_set ; SET(c, d, a, b, 6, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 11 jsr md4_set ; SET(b, c, d, a, 7, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 7 pea 19 jsr md4_set ; SET(a, b, c, d, 8, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 8 pea 3 jsr md4_set ; SET(d, a, b, c, 9, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 7 jsr md4_set ; SET(c, d, a, b, 10, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 11 jsr md4_set ; SET(b, c, d, a, 11, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 11 pea 19 jsr md4_set ; SET(a, b, c, d, 12, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 12 pea 3 jsr md4_set ; SET(d, a, b, c, 13, 7); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 13 pea 7 jsr md4_set ; SET(c, d, a, b, 14, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 14 pea 11 jsr md4_set ; SET(b, c, d, a, 15, 19); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 19 jsr md4_set ; round2 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set2 ; SET(d, a, b, c, 4, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 4 pea 5 jsr md4_set2 ; SET(c, d, a, b, 8, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 8 pea 9 jsr md4_set2 ; SET(b, c, d, a, 12, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 13 jsr md4_set2 ; SET(a, b, c, d, 1, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 3 jsr md4_set2 ; SET(d, a, b, c, 5, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 5 pea 5 jsr md4_set2 ; SET(c, d, a, b, 9, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 9 pea 9 jsr md4_set2 ; SET(b, c, d, a, 13, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 13 jsr md4_set2 ; SET(a, b, c, d, 2, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 2 pea 3 jsr md4_set2 ; SET(d, a, b, c, 6, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 6 pea 5 jsr md4_set2 ; SET(c, d, a, b, 10, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 10 pea 9 jsr md4_set2 ; SET(b, c, d, a, 14, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 13 jsr md4_set2 ; SET(a, b, c, d, 3, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 3 pea 3 jsr md4_set2 ; SET(d, a, b, c, 7, 5); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 7 pea 5 jsr md4_set2 ; SET(c, d, a, b, 11, 9); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 11 pea 9 jsr md4_set2 ; SET(b, c, d, a, 15, 13); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 13 jsr md4_set2 ; round3 ; SET(a, b, c, d, 0, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 0 pea 3 jsr md4_set3 ; SET(d, a, b, c, 8, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 8 pea 9 jsr md4_set3 ; SET(c, d, a, b, 4, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 4 pea 11 jsr md4_set3 ; SET(b, c, d, a, 12, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 12 pea 15 jsr md4_set3 ; SET(a, b, c, d, 2, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 2 pea 3 jsr md4_set3 ; SET(d, a, b, c, 10, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 10 pea 9 jsr md4_set3 ; SET(c, d, a, b, 6, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 6 pea 11 jsr md4_set3 ; SET(b, c, d, a, 14, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 14 pea 15 jsr md4_set3 ; SET(a, b, c, d, 1, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 1 pea 3 jsr md4_set3 ; SET(d, a, b, c, 9, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 9 pea 9 jsr md4_set3 ; SET(c, d, a, b, 5, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 5 pea 11 jsr md4_set3 ; SET(b, c, d, a, 13, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 13 pea 15 jsr md4_set3 ; SET(a, b, c, d, 3, 3); pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea 3 pea 3 jsr md4_set3 ; SET(d, a, b, c, 11, 9); pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea 11 pea 9 jsr md4_set3 ; SET(c, d, a, b, 7, 11); pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea >b_|-$10 pea >b_ pea 7 pea 11 jsr md4_set3 ; SET(b, c, d, a, 15, 15); pea >b_|-$10 pea >b_ pea >c_|-$10 pea >c_ pea >d_|-$10 pea >d_ pea >a_|-$10 pea >a_ pea 15 pea 15 jsr md4_set3 ; This code is the same as md5_process and could be optimized. ; pms->abcd[0] += a; ldy #abcd0 lda [pms],y clc adc >a_ sta [pms],y ldy #abcd0+2 lda [pms],y adc >a_+2 sta [pms],y ; pms->abcd[1] += b; ldy #abcd1 lda [pms],y clc adc >b_ sta [pms],y ldy #abcd1+2 lda [pms],y adc >b_+2 sta [pms],y ; pms->abcd[2] += c; ldy #abcd2 lda [pms],y clc adc >c_ sta [pms],y ldy #abcd2+2 lda [pms],y adc >c_+2 sta [pms],y ; pms->abcd[3] += d; ldy #abcd3 lda [pms],y clc adc >d_ sta [pms],y ldy #abcd3+2 lda [pms],y adc >d_+2 sta [pms],y clean_up anop ; pop the input & restore caller's DP lda RTL+1 sta outputSpace-2 lda RTL sta outputSpace-3 ; pld lda dpEnd tcd ; direct page is not at top of stack tsc clc adc #inputsize+dpsize+directPageonStack <-- not sure why this isn't working? tcs rtl ; The following subroutines are slightly different from md5 md4_set anop set_phd equ 1 set_rts equ set_phd+2 set_s equ set_rts+2 set_k equ set_s+2 set_d equ set_k+2 set_c equ set_d+4 set_b equ set_c+4 set_a equ set_b+4 set_stackEnd equ set_a+4 phd tsc tcd ; #define SET(a,b,c,d,k,s) t=a+F(b,c,d)+X[k] a=ROTATE_LEFT(t,s) pha ; space for return value pha pei t pla sta >t+2 lda t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei t pla sta >t+2 lda set2_k asl a ; multiply by 4 asl a tay lda [t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc #$7999 sta >t lda >t+2 adc #$5A82 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei t pla sta >t+2 lda set3_k asl a ; multiply by 4 asl a tay lda [t sta >t iny iny lda [t+2 sta >t+2 clc lda >t adc #$EBA1 sta >t lda >t+2 adc #$6ED9 sta >t+2 clc lda >t adc [t lda >t+2 ldy #2 adc [t+2 pha ; space for return value pha lda >t+2 pha lda >t pha pei active jeq clean_up ; for (i=0; i < 8; ++i); ; data[i] = (pms->count[i >> 2] >> ((i & 3) << 3)); lda [pms] sta >data ldy #count0+2 lda [pms],y sta >data+2 ldy #count1 lda [pms],y sta >data+4 ldy #count1+2 lda [pms],y sta >data+6 ; md4_append(pms,pad, ((55 - (pms->count[0] >> 3)) & 63) +1); pei pms+2 pei pms pea pad|-$10 pea pad ldy #count0+2 lda [pms],y lsr a sta >temp+2 ldy #count0 lda [pms],y ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda >temp+2 lsr a sta >temp+2 lda >temp ror a sta >temp lda #55 sec sbc >temp and #63 clc adc #1 pea 0 pha jsl >md4_append2 ; md4_append(pms, data, 8); pei pms+2 pei pms pea data|-$10 pea data pea 0 pea 8 jsl >md4_append2 ; for ( i = 0; i < 16; ++i); ; digest[i] = (pms->abcd[i >> 2] >> ((i & 3) << 3)) ldy #abcd0 lda [pms],y sta [digest] ldy #abcd0+2 lda [pms],y ldy #2 sta [digest],y ldy #abcd1 lda [pms],y ldy #4 sta [digest],y ldy #abcd1+2 lda [pms],y ldy #6 sta [digest],y ldy #abcd2 lda [pms],y ldy #8 sta [digest],y ldy #abcd2+2 lda [pms],y ldy #10 sta [digest],y ldy #abcd3 lda [pms],y ldy #12 sta [digest],y ldy #abcd3+2 lda [pms],y ldy #14 sta [digest],y clean_up anop ; pop the input & restore caller's DP lda RTL1+4 sta outputSpace-2 lda RTL1+2 sta outputSpace-4 lda RTL1 sta outputSpace-6 pld tsc clc adc #inputsize tcs clc lda #0 rtl pad dc h'80' dc 63h'00' data ds 8 temp ds 4 end macgen tool128.asm tool128.macros tool128.macros 13/orcainclude/m= 13/appleutil/m= 13/ainclude/m= asml tool128.asm keep=tool128 filetype tool128 tol 0 rename tool128 Tool128 copy -c Tool128 *:system:Tools >q>t  |)  썪 䴍ÍÍ젤ÍÍ젤ÍÍ젤ÍÍ젤ÍÍ젤ÍÍ젤Í̠ݱÍ젤Í̠ݱݲݳÍ젤Í̠ݱݲÍ젤¸Í̠ݱÍ젤øÍ̠ݱݲݳÍ젤ĸÍ̠ݱݲÍ젤Ÿ </******************************************** * * Hash (Tool 128) * * Written by Geoff Weiss * md4 by Andrew Roughan * * Copyright 1999-2002 * ********************************************/ #ifndef __TYPES__ #include #endif #ifndef __HASH__ #define __HASH__ struct mdWorkBlockPtr { long count[2]; /* message length in bits, lsw first */ long abcd[4]; /* digest buffer */ char buf[64]; /* accumulate block */ }; typdef struct mdWorkBlockPtr md5WorkBlockPtr; typdef struct mdWorkBlockPtr >>t  H md4WorkBlockPtr; extern pascal void hashBootInit(void) inline(0x0180,dispatcher); extern pascal void hashStartUp(void) inline(0x0280,dispatcher); extern pascal void hashShutDown(void) inline(0x0380,dispatcher); extern pascal Word hashVersion(void) inline(0x0480,dispatcher); extern pascal void hashReset(void) inline(0x0580,dispatcher); extern pascal void md5Init(md5WorkBlockPtr) inline(0x0980,dispatcher); extern pascal void md5Append(md5WorkBlockPtr, Pointer, long) inline(0x0A80,dispatcher); extern pascal void md5Finish(md5WorkBlockPtr, Pointer) inline(0x0B80,dispatcher); extern pascal void md4Init(md4WorkBlockPtr) inline(0x0C80,dispatcher); extern pascal void md4Append(md4WorkBlockPtr, Pointer, long) inline(0x0D80,dispatcher); extern pascal void md4Finish(md4WorkBlockPtr, Pointer) inline(0x0E80,dispatcher); #endif * Hash Tool Set Macros * by Geoff Weiss * * 9/4/1999 MACRO &lab _hashBootInit &lab ldx #$0180 jsl $E10000 MEND MACRO &lab _hashStartUp &lab ldx #$0280 jsl $E10000 MEND MACRO &lab _hashShutDown &lab ldx #$0380 jsl $E10000 MEND MACRO &lab _hashVersion &lab ldx #$0480 jsl $E10000 MEND MACRO &lab _hashReset &lab ldx #$0580 jsl $E10000 MEND MACRO &lab _hashStatus &lab ldx #$0680 jsl $E10000 MEND MACRO &lab _md5init &lab ldx #$0980 jsl $E10000 MEND MACRO &l>>t   tHab _md5append &lab ldx #$0A80 jsl $E10000 MEND MACRO &lab _md5finish &lab ldx #$0B80 jsl $E10000 MEND MACRO &lab _md4init &lab ldx #$0C80 jsl $E10000 MEND MACRO &lab _md4append &lab ldx #$0D80 jsl $E10000 MEND MACRO &lab _md4finish &lab ldx #$0E80 jsl $E10000 MEND MACRO &lab ~hashBootInit &lab ldx #$0180 jsl $E10000 MEND MACRO &lab ~hashStartUp &lab ldx #$0280 jsl $E10000 MEND MACRO &lab ~hashShutDown &lab ldx #$0380 jsl $E10000 MEND MACRO &lab ~hashVersion &lab ldx #$0480 jsl $E10000 MEND MACRO &lab ~hashReset &lab ldx #$0580 jsl $E10000 MEND MACRO &lab ~hashStatus &lab ldx #$0680 jsl $E10000 MEND MACRO &lab ~md5init &p1 &lab anop ph4 &p1 ldx #$0980 jsl $E10000 MEND MACRO &lab ~md5append &p1,&p2,&p3 &lab ph4 &p1 ph4 &p2 ph4 &p3 ldx #$0A80 jsl $E10000 MEND MACRO &lab ~md5finish &p1,&p2 &lab ph4 &p1 ph4 &p2 ldx #$0B80 jsl $E10000 MEND MACRO &lab ~md4init &p1 &lab anop ph4 &p1 ldx #$0C80 jsl $E10000 MEND MACRO &lab ~md4append &p1,&p2,&p3 &lab ph4 &p1 ph4 &p2 ph4 &p3 ldx #$0D80 jsl $E10000 MEND MACRO &lab ~md4finish &p1,&p2 &lab ph4 &p1 ph4 &p2 ldx #$0E80 jsl $E10000 MEND  !"#$%&'()*+,-./01Programmer's Documentation for the Hash Tool Set (version 1.0.2) Copyright 1999-2004 by Geoff Weiss Additions for MD4 contributed by Andrew Roughan This documentation may not be distributed in hard-copy form for profit. Distributing and/or archiving is restricted while in an electronic form. Any "free" distribution must be given permission by Geoff Weiss in advanced--please contact via email by sending mail to geoff@apple2.gs . There is no guarantee that the right to redistribute this material will be granted. The contents may not be reprinted in part or in whole. The Hash tool set allows GS/OS applications to create a "fingerprint" or message digest from a block of data. The toolset currently provides md5 and md4 checksums. More information can be found online: md5: RFC 1321 - http://www.ietf.org/rfc/rfc1321.txt md4: RFC 1320 - http://www.ietf.org/rfc/rfc1320.txt Software that uses md5 includes the CHAP protocol for PPP, pop email, pdf readers, ssh, and ssl. Software that uses md4 include the Microsoft variant of the CHAP protocol for PPP. To use the Hash Tool Set in an application, it must be started up. Using Orca/M, this is one way to do it: ~LoadOneTool #$80,#$102 ~hashStartUp This toolset is also compatible with the _loadTools call as well. This toolset would not have been written if it wasn't for KFest '99 (http://www.kfest.org/). One of the reasons CHAP didn't make it in Marinetti 2.x was that is requires md5. With the release of Marinetti 3.0b1, PPP now does CHAP if this toolset is installed. The md5 routines were ported to 65816 assembly from the C code by L. Peter Deutsch (ghost@aladdin.com) from Aladdin Systems. The md4 routines were moulded from Geoff's md5 implmentation after Andrew Roughan created C code for md4 in the same style as L. Peter Deutsch's md5. The Hash Tool is system tool number 128 ($80). These are the calls that are available: [ Housekeeping ] hashBootInit hashStartUp hashShutDown hashVersion hashReset hashStatus [ md5 Related ] md5Init md5Append md5Finish [ md4 Related ] md4Init md4Append md4Finish Each md4 and md5 tool call uses a work space called mdWorkBlock. This is a 88-byte work space that needs to be allocated by the calling program. There is no need for programs to access the contents of this work space directly. For reference, this is the structure of this work space: byte $00 - $07 message length in bits, least significant word first byte $08 - $17 digest buffer byte $18 - $57 accumulate block Orca/M Developers can use the M16.HashTool file for the Macros and Equates. This file may be placed in 13:Ainclude for standard library access. Orca/C developers should put Hash.h into 13:OrcaCDefs for include file access. Merlin programmers use HASHTOOL.MACS.S for assembly macros (this file was created by Andrew Roughan). For NiftyList support, copy the lines from the NiftyList Table below and add them to the NList.Data file. If support for tool sets $36 (Apple IIgs TCP/IP, aka Marinetti), $37 (Yet unannounced), or $38 (Time Tool) have not been added, then these lines should go after "1034 Activate...". Otherwise these go after those tool sets. The Hash Tool Set must be started up before using these calls from within NiftyList. If the current application didn't start up the tool set, use these NiftyList commands: _LoadOneTool(80,102) _hashStartUp It is recommended that a copy of the tool set be distributed with any software that requires it. NiftyList Table 0080 === Hash === 0180 hashBootInit() 0280 hashStartUp() 0380 hashShutDown() 0480 hashVersion():Vers 0580 hashReset() 0680 hashStatus():ActFlg 0980 md5Init(@state) 0A80 md5Append(@state,@block,length/4) 0B80 md5Finish(@state,@digest) 0C80 md4Init(@state) 0D80 md4Append(@state,@block,length/4) 0E80 md4Finish(@state,@digest) Errors This tool generates no errors. Changes from 1.0 md5WorkBlock struct from version 1.0 of the tool set is now identified as mdWorkBlock. Both md4 and md5 use the same structure for its work block. The md4 routines are all new. Changes from 1.0.1 There was one section in both md4 and md5 which memory outside of the tool space may have been changed (the case if the DBR and PBR differ). Nothing new has been added. Tool 128 Archive Contents BuildTool128 - Orca/M shell script to build the Hash Tool Hash.h - C header file M16.HashTool - Orca/M assembly macro file Tool128.asm - Hash Tool source code Tool128.docs - This file that you are reading. HASHTOOL.MACS.S - Merlin assembly macro file Tool 128 Reference $0180 hashBootInit Initializes the Hash Tool Set; called only by the Tool Locator. Applications must never make this call. Parameters: The stack is not effected by this call. There are no input or output parameters. Errors: None C extern pascal void hashBootInit(); $0280 hashStartUp Starts up the Hash Tool Set for use by an application. Parameters: The stack is not effected by this call. There are no input or output parameters. Errors: None C extern pascal void hashStartUp(); $0380 hashShutDown Shuts down the Hash Tool Set for use by an application. If your application has started up the Hash Tool Set, the application must make this call before it quits. Parameters: The stack is not effected by this call. There are no input or output parameters. Errors: None C extern pascal void hashShutDown(); $0480 hashVersion Returns the version number of the Hash Tool Set. Parameters: Stack Before Call |________________________________| | wordspace | word -- space for result |________________________________| | | <- SP Stack After Call |________________________________| | versionInfo | word -- version number |________________________________| | | <- SP Errors: None C extern pascal Word hashVersion(); $0580 hashReset Sends a reset to the Hash Tool Set; called only when the system is reset. Applications must never make this call. Parameters: The stack is not effected by this call. There are no input or output parameters. Errors: None C extern pascal void hashReset(); $0680 hashStatus Indicates whether the Hash Tool Set is active. Parameters: Stack Before Call |________________________________| | wordspace | word -- space for result |________________________________| | | <- SP Stack After Call |________________________________| | activeFlag | word -- BOOLEAN; True if tool set is |________________________________| active, false if not. | | <- SP Errors: None C extern pascal Word hashStatus(); $0980 md5Init This call initializes the work block for md5 use. This must be called before any md5Append. The message digest will generate incorrectly if this call is not made. Parameters: Stack Before Call |________________________________| | md5WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md5Init(md5WorkBlkPtr); mdWorkBlockPtr md5WorkBlkPtr; $0A80 md5Append This takes a block of data and takes the message digest of its contents and appends the information to the mdWorkBlock. The block of memory can be 0 bytes long. This call may be used multiple times before calling md5Finish. Parameters: Stack Before Call |________________________________| | md5WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | memoryPtr | Ptr -- pointer to a block of memory |__ ___| | | |________________________________| | memoryLength | long -- Length of block |__ ___| | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md5Append(md5WorkBlkPtr, memoryPtr, memoryLength); mdWorkBlockPtr md5WorkBlkPtr; Ptr memoryPtr; Long memoryLength; $0B80 md5Finish This produces the final md5 message digest. Parameters: Stack Before Call |________________________________| | md5WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | digestPtr | Ptr -- pointer to digest space |__ ___| | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md5Finish(md5WorkBlkPtr, digestPtr); mdWorkBlockPtr md5WorkBlkPtr; Ptr digestPtr; $0C80 md4Init This call initializes the md4 work block. This must be called before any md4Append. The message digest will generate incorrectly if this call is not made. Parameters: Stack Before Call |________________________________| | md4WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md4Init(md4WorkBlkPtr); mdWorkBlockPtr md4WorkBlkPtr; $0D80 md4Append This takes a block of data and takes the message digest of its contents and appends the information to the mdWorkBlock. The block of memory can be 0 bytes long. This call may be used multiple times before calling md4Finish. Parameters: Stack Before Call |________________________________| | md4WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | memoryPtr | Ptr -- pointer to a block of memory |__ ___| | | |________________________________| | memoryLength | long -- Length of block |__ ___| | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md4Append(md4WorkBlkPtr, memoryPtr, memoryLength); mdWorkBlockPtr md4WorkBlkPtr; Ptr memoryPtr; Long memoryLength; $0E80 md4Finish This produces the final md4 message digest. Parameters: Stack Before Call |________________________________| | md4WorkBlkPtr | mdWorkBlockPtr -- pointer to a |__ ___| mdWorkBlock | | |________________________________| | digestPtr | Ptr -- pointer to digest space |__ ___| | | |________________________________| | | <- SP Stack After Call |________________________________| | | <- SP Errors: None C extern pascal void md4Finish(md4WorkBlkPtr, digestPtr); mdWorkBlockPtr md4WorkBlkPtr; Ptr digestPtr; --------------------------------------------------------------------------- Known Bugs: None. Needed Enhancements: It would be cool if this tool set gets upgraded to support md2 (rfc 1319) and sha1 (rfc 3174). Any volunteers? /345>D>t   Op T !SW@H     0H0"0000D