.title check_images .subtitle declarations ; ; program to check selected files for different checksums and ; crc's to see if they have been mofified. This program is ; an advancement over CHECKSUM in that it does more than one ; type of check and it would be extreamly difficult for a ; hacker to make a modification that could still match ; all seven different checks. ; ; Michael N. LeVine ; Code 3514 ; Naval Weapons Center ; China Lake ; Ca 93555 ; (619) 939-3970 ; avn 437-3970 ; ; Arthur E. Ragosta ; removed all but three checks to make it faster ; added device/directory to printout ; ; to add a new crc calc to list-modify the declaration ; of "number_of_crc" below to the new value ; then add to the end of each list below the required ; information as noted ; .enable debug number_of_crc=2 $rmsdef .page .subtitle pure data .psect pure_data,rd,nowrt,noexe,shr,page,gbl,novec ; ; CRC polynomial is specified as outlined in the VAX Architecture ; reference manual entry on the CRC instruction ; ; add new crc polynomial to end of this table crc_poly: .long ^o00120001 ; CRC-16 .long ^xedb88320 ; AUTODIN-II ; ; this table is used when the final CRC is to be extracted from the ; 32 bit long word. This is the length of the CRC (highest order ; element of the CRC polynomial). ; ; add bit length of new crc polynomial to end of this table crc_length: .long 16 ; CRC-16 .long 32 ; AUTODIN-II ; ; What is the starting value of the CRC ? ; usually 0 or -1 ; ; add inital value of new crc polynomial to end of this table crc_init: .long 0 ; CRC-16 .long -1 ; AUTODIN-II ; ; output is to sys$output- a single line generated by SYS$FAO ; useing the format string below ; ; add name of new crc to strings below. Modify list to keep length ; 132 chars or less. format_string: ; item .ascii ?!60 ? ;name .ascii ?Cksum16=%X!XW ? ;chksum16 .ascii ?CRC16=%X!XW ? ;CRC 16 .ascii ?AUTODIN-II=%X!XL? ;AUTODIN-II ; ; no more additions are needed for a new CRC calculation ; format_length=.-format_string ; descripter for FAO format string format: .long format_length .address format_string get_file_arg: ; argument used for LIB$GET_COMMAND .long 4 ; to input name of next file .address file_name ; or files (wild card) to check .address file_prompt .address file_length .address force file_prompt: .ascid /File name ? / ff_arg: .long 3 ; argument list for LIB$FIND_FILE .address file_length ; to step thorough a list of files .address ff_name ; specified by a wild card .address ff_context ffe_arg: ; arguemnt list to LIB$END_FIND_FILE .long 1 ; when done with one file spec .address ff_context ; with all its wild card permutations .page .subtitle impure data .psect impure_data,rd,wrt,noexe,noshr,page,gbl,novec ; ; The CRC tables used by the CRC inst. are built at run time ; and stored here ; crc_tables: .blkl <16*number_of_crc> ; ; the current value of each CRC is stored in this table while ; not in use ; crc_value: .blkl number_of_crc ; ; the file name specification input via the LIB$GET_FOREIGN ; stored below useing 2 descripters, one passing the full ; length of the buffer available, the other getting the ; length of the string read for further processing ; file_name: .long 1024 .address file_string file_length: .long 0 .address file_string file_string: .blkb 1024 ; ; LIB$FIND_FILE found name returned here ; ff_name: .long 1024 .address ff_string ff_length: .long 0 .address ff_string ff_string: .blkb 1024 ff_context: .long 0 ; ; the results of the calculation are converted to ascii string ; and stored in the string below. two descripters are used, one ; to pass to FAO the size of the buffer available, the other to receive ; the length actually used and to pass on the actuall string to be printed ; output_buffer: .long 132 .address output_string output_length: .long 0 .address output_string output_string: .blkb 132 ; ; all checksums are stored below between update calc's ; checksum_16: .long 0 ; ; used by LIB$GET_FOREIGN to force prompt on prompts 2..n ; force: .long 0 .page .subtitle io data structures .psect io_data_structures,rd,wrt,page,noshr,noexe,gbl,novec ; ; for more info-read RMS reference manual ; .align long fab: $fab .align long rab: $rab .align long nam: $nam ; Name block is used to extract full name .align long ; of file to be checked nam_work: .blkb 256 nam_exp: .blkb 256 io_buffer: .blkb 16384 ; buffer to hold part of file for check .page .subtitle once only init .psect code,rd,nowrt,exe,shr,gbl,novec,long .entry check,^m clrl force ;first read-prompt is optional ; ; rebuild the CRC tables for each CRC ; movl #number_of_crc,r11 ; set up loop count for total # of CRC's moval crc_poly,r10 ; start of polynomial table moval crc_tables,r9 ; start of table to store results 10$: pushl r9 ; 2'n arg is addr to store result pushl r10 ; 1'st arg is addr of polynomial calls #2,g^lib$crc_table ; build table for polynomial addl2 #4,r10 ; reset polynomial table to next entry addl2 #<4*16>,r9 ; advance pointer to next table entry decl r11 ; dec CRC counter bgtr 10$ ; if not done-loop back ; when done-fall thorough to per command loop back point .page .subtitle start of per file check loop-get file name and open ; ; loop back point to read in a new file specification ; which can contain wild cards. Program comes back to this ; point only when all files matching input spec have been ; checked ; full_loop_back: ; ; get file name-exit if error or zero length ; callg get_file_arg,g^lib$get_foreign blbs r0,1$ cmpl #rms$_eof,r0 ;exit on <^z> beql 5$ ;on eof-don't output error message $exit_s r0 ;some other error occoured-exit with value 1$: tstw file_length ;also zero length file name bneq 2$ 5$: $exit_s ; take exit without error status 2$: movl #1,force ;subsequent passes-force prompt ; ; at the end of each file checked-the program comes back here ; to see if any more files need to be checked due to wild cards ; in the file spec. ; wild_card_loop_back: movc5 #0,ff_string,#0,#1024,ff_string ;clear string movl #1024,ff_length ;reset length callg ff_arg,g^lib$find_file ;scan for next file blbs r0,7$ ;no error-process next file cmpl #rms$_nmf,r0 ;check for found all files with matching name beql 6$ ;all files found cmpl #rms$_fnf,r0 ;check for none to find beql 9$ $exit_s r0 ;all else kills with status 9$: pushl r0 ;signal file not found calls #1,g^lib$signal 6$: callg ffe_arg,g^lib$find_file_end ;terminate find_file search blbc r0,8$ ; on error-take error exit brw full_loop_back ;go get new file name 8$: $exit_s r0 ;error exit with status 7$: locc #^a/ /,ff_length,ff_string ;find length of file name subl2 r0,ff_length ; ; Haveing found a file matching the specification- now ; set up RMS control blocks for file access ; $fab_store fab=fab,- fac=,- fna=ff_string,- fns=ff_length,- nam=nam,- shr= $rab_store rab=rab,- fab=fab,- rac=seq,- rop= $nam_store nam=nam,- esa=nam_work,- ess=#255,- rsa=nam_exp,- rss=#255 $open fab=fab ;open the file blbs r0,3$ ; if no error continue pushl r0 ; on access failure-signal problem and get next file calls #1,g^lib$signal brw wild_card_loop_back 3$: $connect rab=rab ;connect to open file blbs r0,4$ ; continue on no error pushl r0 ; on connect failure-close file,signal error-try again $close fab=fab calls #1,g^lib$signal brw wild_card_loop_back 4$: ; ; file is now open-fall through to the setup for checks ; .page .subtitle inital crc value, checksums ; ; reload current crc value tables with starting value ; movc3 #,crc_init,crc_value ; ; init checksum values ; clrl checksum_16 .page .subtitle read a block and set up r10,r11 ; ; this section is the top of the loop to read a file ; a chunk at a time for the check-after all checks are ; complete on one chunk-come back here to get the next ; ; read up to 32 blocks from file ; 20$: movc5 #0,io_buffer,#0,#16384,io_buffer;zero the buffer moval io_buffer,rab+rab$l_ubf ;load buffer address movw #16384,rab+rab$w_usz ;load buffer size $read rab=rab ;read section of file into buff blbs r0,21$ ;on no error-contine cmpl #rms$_eof,r0 ;on eof-done-go to final processing bneq 22$ brw 50$ 22$: pushl r0 ;error-close file-log error and try again $close fab=fab calls #1,g^lib$signal ; signal error to user brw wild_card_loop_back ;go get next file to check 21$: moval io_buffer,r11 ;set up pointer to buffer movzwl rab+rab$w_rsz,r10 ;set up actual size of buffer read in .page .subtitle calc checksum s ; ; calc checksum-add 16,32 elements ; ; all adds are done in a 4 byte at a time loop. If the block ; is not mod 2 or 4 in length, the rest of the buffer has been zeroed ; so no effect on the checksum will occour. ; movl r11,r9 ;make local copy of pointer movl r10,r8 ;and size count movl checksum_16,r6 ;the current checksum values 30$: addw2 0(r9),r6 ;do the word checksum addw2 2(r9),r6 addl2 #4,r9 subl2 #4,r8 ;decrement the counter by 4 bytes bgtr 30$ ;if not done-loop back movl r6,checksum_16 .page .subtitle set up and do each crc ; ; do all the CRC's ; set up in a loop one crc at a time ; with no need for user to add code when ; new CRC is added ; ; set up loop counter, pointers for the per CRC loop ; movl #number_of_crc,r9 ;number of crc's to calc moval crc_tables,r8 ;crc table moval crc_value,r7 ;current/inital crc value ; ; loop back point for one pass through per CRC specified ; 40$: crc (r8),(r7),r10,io_buffer ;calc crc movl r0,(r7)+ ;save new crc value back to memory addl2 #<4*16>,r8 ;jump pointer to next CRC table decl r9 ;dec crc counter bgtr 40$ ;and if not done-loop back for next crc brw 20$ ;partial CRC done-loop back for next block to process .page .subtitle close down file ; ; file has been completely processed-close down ; 50$: $close fab=fab .page .subtitle prepare results and display them ; ; use SYS$FAO, build the output string then print it ; ; build on the stack the arguments to SYS$FAO in reverse order ; movl #number_of_crc,r11 ;set up a loop to pushon the CRC's moval >,r10 ;addr of crc length table moval >,r9 ;addr of crc table ; create FAO parameter stack ; push on last to first ; first push on crc values in reverse order 60$: extzv #0,-4(r10),-4(r9),r0 ;extract only significant pushl r0 ;bits of CRC subl2 #4,r10 ;backup one entry in length subl2 #4,r9 ;and crc tables decl r11 ;dec counter bgtr 60$ ;repeat if more crc's to go ; next the checksums in reverse order movzwl checksum_16,-(sp) ; last the first arg(s)-the file name ; use the $NAM block to get only the file name,type and version. ; the rest of the specification (node,device,directory) ; is left off. ;AER movl nam+nam$l_name,-(sp) ;get starting point of name movl nam+nam$l_dev,-(sp) ;get starting point of name addb3 nam+nam$b_name,nam+nam$b_type,r0 ;calc len of name+type addb2 nam+nam$b_dev,r0 ;+device addb2 nam+nam$b_dir,r0 ;+directory addb2 nam+nam$b_ver,r0 ;+version movzbl r0,-(sp) ;and store pushal output_buffer ;output line buffer pushal output_length ;resulting length goes here pushal format ;address of format spec descripter ; number of args ; 3 fao parameters-format str, output buff, output len ; 2 file name string ; 1 checksum's ; x crc's calls #<3+2+1+number_of_crc>,g^sys$fao pushal output_length ;the output length is also a descripter calls #1,g^lib$put_output ;output results brw wild_card_loop_back ;get new file to process .end check