.TITLE VDDRV ;VIRTUAL DISK HANDLER FOR RSX11D/IAS ; COPYRIGHT (C) GLENN C. EVERHART, 1978 ; COPYRIGHT (C) GLENN C. EVERHART, 1979 .IDENT "V002B" .NLIST TTM ; ; MODULE: "VD" ; ; VERSION: V002B ; ; AUTHOR: G. C. EVERHART ; ; 12/16/1978 ; ; THIS HANDLER IS DESIGNED TO ALLOW PROTECTED DATA TO BE STORED ;ON PUBLIC PACKS BY EMULATING A DISK AND KEEPING ALL DATA IN A FILE ;(ONE FILE PER UNIT) NAMED SY0:[1,370]VDDAT0.DAT THRU SY0:[1,370]VDDAT7.DAT ;(FOR THE 8 UNIT CASE). ALL DATA WILL BE ENCRYPTED VIA THE DES ALGORITHM ;PRIOR TO RECORDING AND DECRYPTED ON READING BACK,WITH THIS HANDLER ;CHECKING FOR READ/WRITE PRIVILEGES BY CHECKING THE UIC OF ANY ;TASK REQUESTING THE READ/WRITE. IT SHOULD BE MOUNTED WITH THE /ACP ;SWITCH AND USE AN ACP DIFFERENT FROM THAT OF THE DISK ON WHICH THE ;DATA FILE RESIDES (TO AVOID RE-ENTRANCY PROBLEMS). IT WILL ATTEMPT ;TO MAKE THE DEFAULT ACP "VDAACP", BUT USER CARE IS ADVISED. ; ON STARTUP, THE HANDLER ASKS FOR A 16-CHARACTER ENCRYPTION KEY ;TO USE IN DATA ENCRYPTION. ANY LETTERS A-Z ARE LEGAL AS ARE DIGITS ;(OR BASICALLY ANY ASCII CODES). THE KEY WILL BE READ WITH NO ;ECHO AND USED. ; THE SPECIAL KEY "????????????????" WILL PRODUCE NO ENCRYPTION, ;AND A CONTROL-Z (EOF) ENTERED WILL HAVE THIS EFFECT ALSO. OTHER ;KEYS WILL BE TRANSFORMED AND USED FOR THE ENCRYPTION ALGORITHM. THEY ;WILL IN NO CASE BE STORED ON DISK. A POWER FAIL AST WILL ALSO WIPE ;OUT ALL KEYS AND RESULT IN THE HANDLER DECLARING HARDWARE ERROR ON ALL ;I/O ATTEMPTS THEREAFTER. THE HANDLER MUST BE UNLOADED TO CLOSE ITS ;FILES AND RELOADED TO REENTER THE KEYS. THE SYSTEM SHOULD NOT (AND ;LIKELY CANNOT) BE SAVED WITH THIS HANDLER RESIDENT FOR THESE REASONS. ; ; ; TASKBUILD COMMANDS: ; ;VDDRV/PR/-MU/-FX/-CP/-TA/-AB=VDDRV,VDPRV,[1,1]EXEC.STB/SS ;/ ;TASK=VD.... ;UIC=[1,370] ;UNITS=9 ;ASG=TI:1 ;ASG=SY:2:3:4:5 ;ASG=SY:6:7:8:9 ;PRI=200 ;LIBR=SYSRES:RO ;POOL=150 ;STACK=256 ;;PATCH VDNAM (GBLPAT=VDDRV:VDNAM:"VD") TO CHANGE HANDLER NAME ;// ; ;VDPRV IS A SUBROUTINE TO HANDLE USER PRIVILEGE COMMANDS. ;A SUITABLE DUMMY IS ; .TITLE VDPRV ;VDPRV:: CCC ;SET C=0,Z=0 ; RTS PC ;GO BACK TO VDDRV ; .END ; IF C IS SET ON RETURN, ACCESS WILL BE DENIED ; IF Z IS SET ON RETURN, CHECKING OF UIC WILL BE OVERRIDDEN ; AND ACCESS PERMITTED. ; IF Z AND C ARE CLEAR, ACCESS WILL BE TESTED BY UIC AND ALLOWED ; IF THE UIC OF THE I/O REQUEST IS IN THE ACCESS LISTS IN VDDRV. ; THIS PROGRAM IS MODIFIED FROM A SIMPLE FILE-STRUCTURED ; HANDLER (THE RX11 HANDLER SPECIFICALLY) TO APPEAR AS ; A DISK TO THE SYSTEM BUT IN REALITY TO DO ALL ITS I/O ; TO A FILE SET UP AT TASK LOAD TIME. ; ; A VARIETY OF OPTIONS WILL BE AVAILABLE, PERMITTING ; THE TASK TO ENCIPHER/DECIPHER DATA IN THE FILE FROM ; AN IN-CORE-ONLY KEY AND TO DO I/O ONLY TO THAT ; FILE ALREADY DEFINED. THIS WILL PERMIT SYSTEM MANAGERS ; TO ENFORCE DISK USE QUOTAS ON USERS, AND/OR TO PROVIDE ; SECURE DATA BASES ON DISK THAT MAY BE READ ONLY BY THOSE ; WHO HAVE THE KEY. THIS TASK MAY CHECK A SPECIAL BIT ; (IF THE USER DESIRES AND PROVIDES A SUITABLE VDPRV SUBROUTINE) ; IN THE PUD OF THE TASK'S TI FOR ENCODE/DECODE PRIVILEGES ; AND WILL FURTHER HAVE AN OPTIONAL LIST OF UIC'S THAT ; ARE PERMITTED TO ACCESS SENSITIVE FILES. A TASK NOT ; RUNNING UNDER ONE OF THE PERMITTED UIC'S WILL READ ; GARBAGE AND NEVER WRITE ANYTHING. ; ; THE OPTION OF AN UN-CIPHERED PSEUDO-DISK WILL ALSO BE ; PROVIDED (FOR THE SPACE LIMIT FUNCTION), WITH ALL AND ; SUNDRY PERMITTED ACCESS. (THE OPTION OF RESTRICTED ACCESS ; AND UNCIPHERED DATA WILL ALSO BE ALLOWED, BUT WILL BE LESS ; USEFUL, THOUGH FASTER...THE ENCIPHERING/DECIPHERING WILL ; HAVE TO BE DONE IN A SUBROUTINE IN THE HANDLER.) ; ; N.B. THIS HANDLER ****MUST**** HAVE A DIFFERENT DEFAULT ; AND ACTUAL ACP THAN THE DISK TO WHICH IT DOES I/O!!!! ; OTHERWISE YOU MAY GET RE-ENTRANCY PROBLEMS IN ; F11ACP AND ROYALLY SCREW UP THE SYSTEM IN CORE AND POSSIBLY ; ON DISK!! ; ; IF THE ASSEMBLY PARAMETER "DESOUT" IS DEFINED, THE ENCRYPTION ;ALGORITHM WILL BE A RELATIVELY SIMPLE (BUT FAST) ALGORITHM THAT WILL ;PROVIDE SOME DATA SECURITY BUT NOT AGAINST DETERMINED CRYPTOGRAPHIC ;EFFORTS. IF IT IS UNDEFINED (DEFAULT), AN ENCRYPTION ALGORITHM SIMILAR ;TO THE DATA ENCRYPTION STANDARD WILL BE USED WHICH, WHILE SLOW, ;PROVIDES EXCELLENT DATA SECURITY. ; .SBTTL SYMBOL & MACRO DEFINITIONS .MCALL CLEF$S,WTSE$S,SPRA$S,ASTX$S,CALL,RETURN .MCALL EXIT$S,WTLO$S,SETF$S,MRKT$,CMKT$,DIR$ ; ;DATA BUFFER .IF NDF,MAXUNI MAXUNI=8. ;ALLOW 8. UNITS FOR THE PRESENT .ENDC WRT=1 ;WRITE (TRANSFER DIRECTION) KEYDAT: DATBUF: .BLKW 256. ;1 BLOCK PER BUFFER ; ONLY 1 BUFFER NEEDED IN THE HANDLER...ALL ACCESS IS SERIAL ANYHOW. DATCNT: .WORD 0 ;BYTE COUNT FOR CURRENT OPERATION DATBLK: .WORD 0,0 ;VIRTUAL BLOCK NUMBER FOR CURRENT OPERATION ; KEYMSG: .ASCII <15><12>/ENTER 16 CHAR. KEY & ACC. CODE FOR VD/ KEYUNI: .ASCII /0:/ KEYOSZ=.-KEYMSG .EVEN .GLOBL CIPHPW ;ACCESS KEYS FOR EACH UNIT ;INTERPRETATION: ; 0=NORMAL DEFAULT ACCESS CODE ; 1=ACCESS CHECKS FOR VDPRV CODE A ; 2=SIMPLE ENCRYPT/DECRYPT CODE B ; 4=DEFEAT ACCESS ALWAYS CODE D ; 8=ALLOW ACCESS ALWAYS CODE H CIPHPW: .BLKB MAXUNI .BYTE 0 ;SAFETY .EVEN .SBTTL FDB AREAS FOR FILES .D.D..=0 .MCALL FDBDF$,FDAT$A,FDBK$A,FDOP$A,FDRC$A .MCALL NMBLK$ .MACRO SETFS N,LUNNO FDB'N:: FDBDF$ FDAT$A R.FIX,,1000,-16.,-16. FDRC$A FD.RWM FDBK$A DATBUF,512.,,,IOST'N FDOP$A ,DSD'N,DFNB'N,FO.MFY,FA.DLK DSD'N:: .WORD 4,DEV'N .WORD FL'N,DIR'N .WORD FNL'N,FN'N DFNB'N: NMBLK$ VDDAT'N,DAT,,SY,0 FN'N:: .ASCII /VDDAT/ .BYTE ''N .ASCII /.DAT/ FNL'N=.-FN'N .EVEN DIR'N:: .ASCII /[01,370]/ FL'N=.-DIR'N .EVEN DEV'N:: .ASCII /SY0:/ .EVEN IOST'N: .WORD 0,0 .ENDM .REPT MAXUNI ;SET UP "MAXUNI" FDB'S SETFS \.D.D..,.D.D.. .D.D..=.D.D..+1 .ENDR .D.D..=0 FDBTBL:: ;TABLE OF FDB ADDRESSES FOR EACH LUN USED .MACRO FDBWRD N .WORD FDB'N .ENDM .REPT MAXUNI ;SET UP "MAXUNI" FDB'S FDBWRD \.D.D.. .D.D..=.D.D..+1 .ENDR ; .MACRO ERROR CODE MOV #CODE&377,R3 .ENDM ; EF.NIR=000001 ; EVENT FLAG MASK FOR "NORMAL" REQUEST TRIGGER EF.XIR=000002 ; EVENT FLAG MASK FOR "EXPRESS" REQUEST TRIGGER UF.RH=200 ; INTFLG= 4 ; EFN MASK FOR I/O DONE (EFN 3) KEYS: .REPT MAXUNI .WORD 0,0,0,0 ;64 BIT ENCRYPTION/DECRYPTION KEY .ENDR ; PSW=177776 .MCALL FSRSZ$ FSRSZ$ 0 ;USE QIO$ ONLY (READ/WRITE MODE TYPE I/O) .PAGE .SBTTL READ IN KEYS ;LOAD KEYS FROM 16 CHARACTER DATA. USE LOW 4 BYTES OF EACH CHARACTER ;FOR 4 BITS OF KEY. THEN SCRAMBLE A BIT TO MAKE IT HARDER TO FIND KEY BY ;EXAMINING CORE. KGT: JSR PC,S.RSAV ;SAVE REGS MOV #MAXUNI,R1 ;DO ALL KEYS MOV #KEYS,R2 .MCALL QIOW$S 10$: QIOW$S #IO.WVB,#1,#3,,#IOST0,,<#KEYMSG,#KEYOSZ,#40> ;ASK FOR KEY INCB KEYUNI ;SET TO ASK FOR NEXT CRYPTION KEY QIOW$S #IO.RNE,#1,#3,,#IOST0,,<#KEYDAT,#20.,#40> ;READ IT IN ;NOTE IO.RNE MEANS NO ECHO OF KEY ;USE UNIT 0'S IO STATUS BLOCK FOR CONVENIENCE HERE.... MOV #-1,@R2 ;PRESET NO ENCRYPTION MOV #-1,2(R2) MOV #-1,4(R2) MOV #-1,6(R2) ;(KEYS ALL -1'S=NO CODE) TSTB IOST0 ;NOW SEE IF THERE WERE ERRORS READING KEY IN BMI 11$ ;YES MOV #KEYDAT,R5 ;NO, DECODE KEY TO BINARY MOV #4,R3 ;4 WORDS / KEY 13$: CLR R0 ;SET UP RECEPTACLE FOR A WORD MOV #4,R4 ;4 LETTERS/WORD 12$: ASH #4,R0 ;SHIFT UP 1 LETTER MOVB (R5)+,-(SP) ;LOAD A CHARACTER BIC #-20,(SP) ;LEAVE LOW 4 BITS ONLY BIS (SP)+,R0 ;PUT INTO R0 ACC. DEC R4 BGT 12$ ;DO WHOLE WORD MOV R0,(R2)+ ;SAVE WORD OF KEY DEC R3 ;DONE WHOLE KEY BGT 13$ ;NO, DO NEXT WORD ;LOAD ACCESS BYTE FOR KEY FROM LAST CHARACTER ENTERED IF 40 OR MORE OCTAL CMPB @R5,#40 ;SPACE OR BIGGER? BLO 70$ ;NO, NOTHING SPECIAL, LEAVE ALONE ACCESS KEY MOVB @R5,-(SP) ;YES, GET ACCESS RIGHTS FROM LOW 5 BITS BIC #-40,@SP ;ZAP ALL OTHERS MOV #MAXUNI,R5 ;CONSTRUCT UNIT NUMBER SUB R1,R5 ;0,1,2,...ETC. ADD #CIPHPW,R5 ;POINT AT ACCESS KEY BYTE MOVB (SP)+,@R5 ;AND FILL ACCESS BYTE. (NOTE DATA AREA CLEARED ;AFTER USE SO WON'T GET HERE UNLESS 17 TH CHAR ;IS TYPED IN. 70$: ;NOW DONE WHOLE KEY, SO... JSR PC,FUDGIT ;...MOVE IT AROUND A BIT 11$: DEC R1 ;DONE ALL UNITS BGT 10$ ;NO, DO NEXT MOV #256.,R0 ;YES, CLEAR DATA AREA NOW MOV #DATBUF,R1 15$: CLR (R1)+ ;ZERO WHOLE DATA AREA DEC R0 BGT 15$ JSR PC,S.RRES ;GET HANDLER'S REGS BACK RTS PC .SBTTL REGISTER SAVE/RESTORE SUBS .GLOBL S.RSAV,S.RRES ;LET VDPRV USE THESE SUBS ;REGISTER SAVE/RESTORE. CALL VIA JSR PC,S.RSAV OR JSR PC,S.RRES. ;ALL REGISTERS UNCHANGED ACROSS CALLS TO SAVE REGS. S.RSAV: MOV R5,-(SP) MOV R4,-(SP) MOV R3,-(SP) ;JSR PC,S.RSAV MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) JMP @14(SP) ;BACK TO CALLER, REGS UNCHANGED S.RRES: MOV (SP)+,14(SP) ;BASH RETURN ADDRESS MOV (SP)+,R0 MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 ;JSR PC,S.RRES MOV (SP)+,R4 MOV (SP)+,R5 RTS PC ;BACK TO CALLER WITH OLD REGS ; ; .SBTTL INITIALIZATION AND DEQUEING CODE BEGIN:: SPRA$S #VDPWR ; SETUP POWER-FAIL AST BCC 5$ ; AST SETUP FAILED, EXIT JMP VDXIT ; HANDLER TASK 5$: MOV #VDUIT,R0 ; START OF UIT TABLE MOV #"VD,R2 ; MOVE NAME INTO R2 VDNAM==.-2 ;ALLOW GLOBAL BASH OF DEVICE NAME. MOV #UF.RH,R3 ; FLAGS BYTE FOR PUDS. CALL ..DSUT ; DECLARE HANDLER RESIDENT. BCC 6$ ; SUCCESS ? JMP VDXIT ; NO--DECLARE FAILED ;EXIT. 6$: MOV 12(R0),R2 ; MOVE PUD ADDRESS INTO R2 ;N.B. -- NO INTERRUPTS HANDLED HERE. I/O VIA FCS TO A REAL DISK... ;(USE READ$/WRITE$ BUT WAIT FOR INTERMEDIATE OPERATIONS (WITH TIMEOUT) ;IF TRANSFER IS LONGER THAN 256 WORDS...) MOV #VDUIT,R0 ; SET R0 TO POINT TO ; UIT TABLE. JSR PC,KGT ;GET KEYS LOADED NOW... CLEF$S #3 ; CLEAR INT. EVENT FLAG. ;N.B.--BUILD WITH LARGE STACK. START CODE WILL CONTAIN COMMAND SEQUENCE ;AND SHOULD NOT BE OVER-WRITTEN. ; ; OPEN FILES ON ALL UNITS USING FDBTBL TO ACCESS FDB'S. ; FOR FIRST GO, USE FIXED FILE NAMES IN FIXED ACCOUNTS TO ; DO EACH VIRTUAL DISK. NOTE THAT THESE MUST BE PRE-ALLOCATED ; SOMEHOW (THIS TASK WILL NEVER EXTEND THEM) AND MUST BE NAMED ; APPROPRIATELY. THERE WILL BE A SAVING IN THAT PARSE LOGIC NEED ; NOT BE BUILT INTO THIS HANDLER. HOWEVER, IF ANYONE IS USING ; [1,370] FOR ANYTHING OR ALREADY HAS FILES NAMED AS WE WANT ; HERE, THE HANDLER WILL NEED TO CHANGE TO ACCOMODATE THAT. ; ; INITIAL TEST WILL NOT ATTEMPT TO ENCRYPT/DECRYPT DATA BUT WILL ; SIMPLY MOVE IT INTO FILE STRAIGHT. LATER THE ENCRYPT/DECRYPT ; SUBROUTINES WILL BE BUILT IN AND STARTUP WILL ASK ON LUN 1 FOR ; KEYS. FILES ARE ACCESSED ON LUNS 2 UP AND USE EVENT FLAGS 16 UP ; TO AVOID CONFLICT WITH NORMAL HANDLER OPERATIONS. ; N.B. THIS TASK PRIORITY SHOULD BE LESS THAN THE ACP IT USES ; AND THAT ACP SHOULD NOT BE F11ACP UNLESS THE DISK USED FOR SY0: ; IS USING ANOTHER ACP. ; JSR PC,S.RSAV ;PRESERVE HANDLER REGS MOV #MAXUNI,R1 ;DO ALL POSSIBLE PUDS. 8$: CMP R2,#MAXUNI ;IS A PUD REALLY THERE? BLOS 25$ ;NO, LEAVE STUFF ALONE. CMP #^RF11,U.DACP(R2) ;IS DEFAULT ACP F11ACP? BNE 10$ ;NO, ALL PROBABLY IS WELL MOV #^RVDA,U.DACP(R2) ;YES, SET SO VDAACP IS DEFAULT 10$: ADD #6,R0 ;POINT AT NEXT PUD POINTER MOV 12(R0),R2 ;PUD ADDR NOW IN R2 DEC R1 BGT 8$ ;TEST ALL PUD DEFAULT ACP'S 25$: JSR PC,S.RRES ;GET BACK HANDLER REGS JSR PC,S.RSAV ;ALL REGS FREE, SO OPEN ALL FDB'S MOV #MAXUNI,R5 ;NO. UNITS DEFINED FOR THIS HANDLER MOV #FDBTBL,R4 ;AND FDB ADDRESSES 11$: MOV (R4)+,R0 ;POINT R0 AT FDB SET UP NOW .MCALL OPEN$M,CLOSE$ OPEN$M ;R0 ALREADY IS FDB. ;OPEN THE FILE (SET UP ALREADY...) ;NOW SET UP PUD FOR NUMBER OF BLOCKS IN THE NOW-OPEN FILE BCS 12$ ;IF BAD OPEN,FORGET IT! MOV R4,R3 ;GET UNIT SUB #,R3 ;0,2.4.6.... MUL #3,R3 ;MAKE IT A UIT OFFSET MOV VDUIT+12(R3),R3 ;POINT AT PUD NOW WITH R3 ; R0 IS FDB; R3 IS PUD CMP R3,#MAXUNI ;IS IT REALLY A PUD??? BLOS 12$ ;IF NOT, DON'T TRY TO CHANGE IT. MOV F.EFBK+2(R0),U.LBN(R3) ;SAVE LOW ORDER NO. BLOCKS MOV F.EFBK+0(R0),U.LBH(R3) ; AND HIGH ORDER NO. SUB #1,U.LBN(R3) ;ADJUST FOR BOOT BLOCK NUMBERING SBC U.LBH(R3) ;(32 BIT ADJUSTMENT...) 12$: DEC R5 BGT 11$ ;OPEN MAXUNI FILES JSR PC,S.RRES ; ; ; VDIDLE: TST XITFLG ; IS HANDLER EXITING BNE VDEXIT ; YES WTLO$S 0,#EF.NIR!EF.XIR ; WAIT FOR REQUEST EVENT FLAGS DOMORE: MOV .CRTSK,R5 ; LOOK AT EVENT FLAGS BIT #EF.XIR,A.EF(R5) ; SOMETHING EXPRESS REQUESTS TO DEQUE? BEQ 10$ ; NO! TRY FOR NORMAL ONES CALL ..DQRE ; YES! TRY TO DEQUEUE IT BCC 20$ ; GOT ONE! PROCESS IT 10$: BIT #EF.NIR,A.EF(R5) ; IS THERE A NORMAL ONE? BEQ VDIDLE ; NOPE! SLEEP. CALL ..DQRN ; YES! TRY TO DEQUEUE IT BCS VDIDLE ; NO CAN DO. SLEEP 20$: ; A REQUEST HAS BEEN DEQUEUED. ; R0=#VDUIT, R1=REQ NODE ; ADDR, R2=UIT UNIT ENTRY ; WHICH POINTS TO PUD PTR. ; ADV UIT TABLE POINTER TO MOV R2,-(SP) ; =RNA ADDRESS ENTRY FOR ; NORMAL REQUESTS ADD #2,(SP) BIT #RF.XR,R.FC(R1) ; WAS THE FCN AN EXPRESS BEQ 30$ ; REQUEST? ADD #2,(SP) ; YES--ADV PTR TO RNA ; FOR EXPRESS REQUESTS 30$: CLR @(SP)+ ; 0 RNA ENTRY IN UIT TBL. CMPB R.FC+1(R1),#VDMXFC ; IS I/O FUNCTION CODE BHI VDINV ; OUT OF RANGE? CALL ..VACC ; NO--VALIDATE ACCESS RIGHTS. BCS ACVIOL ; ACCESS VIOLATION? 40$: JMP ..DISP ; NO--DISPATCH FUNCTION. .PAGE VDINV: ERROR IE.IFC ; COME HERE FOR ALL INVALID BR FINISH ; I/O FUNCTION CODES. ACVIOL: ERROR IE.PRI ; HERE IF ACCESS VIOLATION BR FINISH GOODRQ: ERROR IS.SUC ; ALL GOOD REQUESTS CAN END HERE FINISH: ; ALL I/O COMPLETE CONVERGES ; HERE. R3,R4 HAVE BEEN ; PRESET TO IOSB VALUES. CLR R2 ; CLEAR ADJUSTMENT TO UNITY. CALL ..IODN ; DO I/O DONE. MOV #VDUIT,R0 ;RESTORE UIT PTR BR DOMORE ; GO TRY ANOTHER DEQUE .PAGE .SBTTL FUNCTION CODE WORK DONE HERE VDATT: CALL ..ATUN ; ATTEMPT TO ATTACH (PER R1,R2) BCC GOODRQ ; WAS SUCCESSFUL. FINISH UP ERROR IE.DAA ; ATTACH FAILED BR FINISH ; VDDET: CALL ..DTUN ; ATTEMPT DETACH (PER R1,R2) BCC GOODRQ ; DETACH WAS SUCCESSFUL ERROR IE.DNA ; BAD DETACH BR FINISH ; IORUND: CALL ..FLSH ; FLUSH ALL I/O REQUESTS ; FOR THIS TASK. CALL ..FIFL ; DE-ACCESS OPEN FILES ? BR GOODRQ ; BADSR: ERROR IE.SRE ; HERE IF SEND & REQUEST BR FINISH ; FAILED TO DISPATCH TO ; AN AUXIALARY TASK. ; UNLOAD: MOV R1,XITFLG ; SAVE RNA IN XITFLG MOV (R2),-(SP) ; SAVE PUD POINTER BR DOMORE ; GO FINISH ALL OTHER ; REQUESTS & RETURN TO ; VDEXIT WHEN DONE. VDEXIT: MOV XITFLG,R1 ; RESTORE RNA OF EXIT ; REQUEST. CLR R2 ; SET ADJUSTMENT TO UNITY ERROR IS.SUC ; SET SUCCESSFUL EXIT CALL ..IODN ; DO I/O DONE MOV (SP)+,R0 ; GET PUD POINTER JSR PC,S.RSAV ; ACQUIRE ALL REGS FOR A MOMENT... MOV #MAXUNI,R5 ;CLOSE FILES ON DISK MOV #FDBTBL,R4 1$: MOV (R4)+,R0 CLOSE$ R0 ; CAN'T DMO SY: UNLESS FILES CLOSED! ; THEREFORE ONLY CLOSE WHEN THIS HANDLER ; EXITS SO CAN'T SAVE SYSTEM WITH IT ; LOADED! (DON'T WANT KEY TO ENCRYPTION ; TO BE KNOWN ALL THE TIME...SHOULD HAVE ; TO BE RE-ENTERED AT EVERY BOOT.) DEC R5 BGT 1$ ;CLOSE THEM ALL AT HANDLER UNLOAD (AND ONLY ; THEN, TO ENSURE SYS NOT SAVED WITH HANDLER ; LOADED) JSR PC,S.RRES NONRSD: MOV #VDUIT,R0 ; SET POINTER TO UIT TABLE CALL ..DNRC ; AND DECLARE NON RESIDENT. VDXIT: EXIT$S ; DO THE EXIT ; ; ; SPECIAL FUNCTION CODE PROCESSOR ; ; TAKES CARE OF THE FOLLING FUNCTIONS: ; 1. I/O RUN DOWN ; 2. HANDLER EXIT (UNLOAD) ; SPCFCN: TST R.AT(R1) ; IS THIS REQUESTED BY EXEC.? ; (I.E. CHECK ATL NODE=0=QUEUED) BNE VDINV ; NO-- INVALID REQUEST. CMP R.FC(R1),#IO.RDN ; IS IT I/O RUNDOWN BEQ IORUND ; ? CMP R.FC(R1),#IO.UNL ; NO--IS IT HANDLER EXIT? BEQ UNLOAD BR VDINV ; ILLEGAL FUNCTON ; ; ; POWER UP INIT CODE. EXECUTED ON POWER-FAIL RECOVERY OR SYSTEM REBOOT. ; VDPWR: JSR PC,S.RSAV ;CLEAR OUT ANY RESIDENT KEYS FOR ENCRYPTION/DECRYPTION .IF NDF,NOCLKY MOV #,R0 MOV #KEYS,R1 1$: CMP @R1,#-1 ;UNENCODED FILES MAY STILL BE USED... BNE 3$ TST (R1)+ ;...AFTER PWR UP BR 2$ 3$: CLR (R1)+ ;BUT CODES MUST BE REMOVED HERE. 2$: DEC R0 BGT 1$ ;ZERO ENTIRE KEY TABLE .ENDC JSR PC,S.RRES ASTX$S ; BYE! .PAGE ; ; .SBTTL READ - WRITE CODE ;READ/WRITE LOGICAL BLOCK WRITE: MOV R.PB+2(R1),R3 ;GET NO. OF BYTES TO WRITE BEQ 1$ ;ZERO IS ILLEGAL, TURKEY! MOV R.PB(R1),R2 ;GET VIRTUAL BUFFER ADDRESS MOV #WRT,R5 ;WRITE (TRANSFER DIRECTION) JSR PC,@#..VXFR ;VERIFY TRANSFER BCC 55$ 1$: JMP BADADR ;SORRY, BAD BUFFER 55$: ; JSR PC,BUFCLR ;ZERO DATA AREA FIRST... JSR PC,S.RSAV ;ACQUIRE REGS. CAN'T LET REST OF HANDLER ; GET CLOBBERED. MUCH NONSENSE HERE... ;NOW FIND OUT WHERE OUR DATA BUFFER IS PRIOR TO CALLING ..BLXI. ;NOTICE THAT WE DON'T REALLY CARE WHETHER 18 OR 22 BIT MAPPPING IS ;ON, SINCE WE DO DMA ONLY VIA FCS TO/FROM OUR ADDRESS SPACE. ;WE WILL EVENTUALLY PUT ENCODING/DECODING BETWEEN DATA COPY AND ;TRANSFER TO OR FROM DISK. MOV #DATBUF,R4 ;R4 NOW IS DATA ADDRESS OF OUR BUFFER MOV R.PB+2(R1),DATCNT ;SAVE BYTES TO COPY MOV R.PB+10(R1),DATBLK ;...LOW BLOCK NUMBER... MOV R.PB+6(R1),DATBLK+2 ;AND HIGH BLOCK NUMBER... ADD #1,DATBLK ;ADJUST BLK # UP 1 FOR VIRTUAL BLOCKS ADC DATBLK+2 ;N.B. IF TRANSFER IS FOR OVER 32K WORDS -256 WORDS, SCREW UP LIKELY... ; MUST HAVE SOME WAY TO TELL IF WE'RE DONE... SUB #512.,R2 ;SET UP BUFFERR ADDR LOW TO START UP CMP DATCNT,#177000 ;SEE IF TOO BIG BLO 2$ ;OK JSR PC,S.RRES ;BAD. JMP BADADR ;SO TELL USER 2$: ;N.B. IF IT WERE REALLY IMPORTANT TO CONFUSE THE USER, WE COULD AT THIS ;POINT SCRAMBLE THE BLOCK NUMBERS IN THE DISK. HOWEVER, THIS WOULD ;PROBABLY LEAD TO ALL KINDS OF EXTRA PAGE-TURNING DELAYS WITHIN F11ACP ;AS IT READS NEW MAPS INTO CORE AND IS THEREFORE OMITTED FOR PERFORMANCE ;REASONS. (THIS HANDLER WILL BE SLOW ENOUGH WITHOUT FURTHER NONSENSE!) ADD #512.,R2 ;BUMP BUFF ADDR OF CALLER THIS MUCH EACH TIME CMP R3,#512. ;SEE IF TRANSFER FITS BLOS 4$ ;ALL WELL...GO TO IT! MOV #512.,R3 ;BYTES TO COPY 4$: SUB R3,DATCNT ;ACCOUNT FOR DATA TO DO... JSR PC,@#..BLXI ;TRANSFER DATA TO TASK SPACE BCC 5$ ;IF ALL WELL, ACCOUNT FOR THIS PART XFER JSR PC,S.RRES ;IF ANY ERRORS, LOSE. JMP BADADR ;RETURN ERROR, DO NO MORE QIO$'S 5$: JSR PC,S.RSAV ;PREPARE TO ENCRYPT DATA PRIOR TO WRITING IT JSR PC,ENCRYP ;ENCRYPT IT JSR PC,S.RRES JSR PC,S.RSAV ;SAVE REGS AROUND FCS QIO MOV VDUIT+4,R0 ;UNIT NO. ASL R0 ;OFFSET INTO FDB TBL MOV FDBTBL(R0),R0 ;FDB ADDRESS NOW FOR THIS UNIT MOV #IO.WVB,R1 ;WRITE VIRTUAL BLOCK HERE... MOV #5,R2 ;5 PARAMETERS MOV DATBLK,-(SP) ;LOW BLOCK NUMBER MOV DATBLK+2,-(SP) ;HIGH BLOCK NUMBER CLR -(SP) ;COMPATIBILITY WORD MOV #512.,-(SP) ;TRANSFER LENGTH IN BYTES MOV R4,-(SP) ;LOCAL BUFFER ADDRESS MOV SP,R3 ;POINT R3 AT PARAMETER BLOCK JSR PC,.XQIO ;CALL THE FCS QIO ROUTINE JSR PC,BUFCLR ;THEN CLEAR LOCAL BUFFER ADD #12,SP ;REMOVE PARAMETER BLOCK ADD #1,DATBLK ;BUMP VIRTUAL BLK # ADC DATBLK+2 ;32 BIT ADD... TSTB F.ERR(R0) ;DID ALL GO WELL? BPL 11$ ;YES IF BRANCH JSR PC,S.RRES ;NO, BAD TRANSFER SOMEHOW... JSR PC,S.RRES ;RESTORE BOTH SETS REGS...SAVED TWICE. JMP ILLBLK ;REPORT AS BAD BLOCK (MOST LIKELY ERR) 11$: JSR PC,S.RRES MOV DATCNT,R3 ;GET NUMBER OF BYTES LEFT IN XFER BEQ 6$ ;IF ZERO, WE'RE DONE CMP DATCNT,#177000 ;OR IF NEGATIVE, DONE BHIS 6$ BR 2$ ;IF NOT, MORE LEFT TO DO 6$: JSR PC,S.RRES ;GET BACK REGISTERS FOR HANDLER MOV R.PB+2(R1),R4 ;SAVE NO. BYTES TRANSFERRED AS NO. REQUESTED JMP GOODRQ ;THEN LEAVE CLAIMING ALL WAS WELL ; READ: MOV R.PB+2(R1),R3 ;GET NO. OF BYTES TO READ MOV R.PB(R1),R2 ;GET VIRTUAL BUFFER ADDRESS CLR R5 ;READ (TRANSFER DIRECTION) JSR PC,@#..VXFR ;VERIFY TRANSFER BCC 102$ JMP BADADR ;BUFFER IS ILLEGAL 102$: JSR PC,S.RSAV ;ACQUIRE REGS. CAN'T LET REST OF HANDLER ; GET CLOBBERED. MUCH NONSENSE HERE... ;NOW FIND OUT WHERE OUR DATA BUFFER IS PRIOR TO CALLING ..BLXI. ;NOTICE THAT WE DON'T REALLY CARE WHETHER 18 OR 22 BIT MAPPPING IS ;ON, SINCE WE DO DMA ONLY VIA FCS TO/FROM OUR ADDRESS SPACE. ;WE WILL EVENTUALLY PUT ENCODING/DECODING BETWEEN DATA COPY AND ;TRANSFER TO OR FROM DISK. JSR PC,BUFCLR ;INIITIALLY ZERO BUFFER MOV #DATBUF,R4 ;R4 NOW IS DATA ADDRESS OF OUR BUFFER MOV R.PB+2(R1),DATCNT ;SAVE BYTES TO COPY MOV R.PB+10(R1),DATBLK ;...LOW BLOCK NUMBER... MOV R.PB+6(R1),DATBLK+2 ;AND HIGH BLOCK NUMBER... ADD #1,DATBLK ;ADJUST BLK # UP 1 FOR VIRTUAL BLOCKS ADC DATBLK+2 ;N.B. IF TRANSFER IS FOR OVER 32K WORDS -256 WORDS, SCREW UP LIKELY... ; MUST HAVE SOME WAY TO TELL IF WE'RE DONE... SUB #512.,R2 ;SET BUFFER VIRTUAL ADDR LOWER TO START UP... CMP DATCNT,#177000 ;SEE IF TOO BIG BLO 2$ ;OK JSR PC,S.RRES ;BAD. JMP BADADR ;SO TELL USER 2$: ADD #512.,R2 ;BUMP CALLER BUFF. ADDR EVERY TIME CMP R3,#512. ;SEE IF TRANSFER FITS BLOS 4$ ;ALL WELL...GO TO IT! MOV #512.,R3 ;BYTES TO COPY 4$: SUB R3,DATCNT ;ACCOUNT FOR DATA TO DO... JSR PC,S.RSAV ;SAVE REGS AROUND FCS QIO MOV VDUIT+4,R0 ;UNIT NO. ASL R0 ;OFFSET INTO FDB TBL MOV FDBTBL(R0),R0 ;FDB ADDRESS NOW FOR THIS UNIT MOV #IO.RVB,R1 ;READ VIRTUAL BLOCK HERE... MOV #5,R2 ;5 PARAMETERS MOV DATBLK,-(SP) ;LOW BLOCK NUMBER MOV DATBLK+2,-(SP) ;HIGH BLOCK NUMBER CLR -(SP) ;COMPATIBILITY WORD MOV #512.,-(SP) ;TRANSFER LENGTH IN BYTES MOV R4,-(SP) ;LOCAL BUFFER ADDRESS MOV SP,R3 ;POINT R3 AT PARAMETER BLOCK JSR PC,.XQIO ;CALL THE FCS QIO ROUTINE ADD #12,SP ;REMOVE PARAMETER BLOCK ADD #1,DATBLK ;BUMP VIRTUAL BLK # ADC DATBLK+2 ;32 BIT ADD... TSTB F.ERR(R0) ;DID ALL GO WELL? BPL 11$ ;YES IF BRANCH JSR PC,S.RRES ;NO, BAD TRANSFER SOMEHOW... JSR PC,S.RRES ;RESTORE BOTH SETS REGS...SAVED TWICE. JMP ILLBLK ;REPORT AS BAD BLOCK (MOST LIKELY ERR) 11$: JSR PC,S.RRES JSR PC,S.RSAV ;PREPARE TO ENCRYPT DATA JSR PC,DECRYP ;DECRYPT DATA FROM DISK TO CALLER JSR PC,S.RRES ;DATA IN BUFFER (R4 =ADDR, 512 BYTES) JSR PC,@#..BLXO ;TRANSFER DATA TO TASK SPACE BCC 5$ ;IF ALL WELL, ACCOUNT FOR THIS PART XFER JSR PC,S.RRES ;IF ANY ERRORS, LOSE. JMP BADADR ;RETURN ERROR, DO NO MORE QIO$'S 5$: JSR PC,BUFCLR ;ZERO DATA AREA WHEN BUFFER USED MOV DATCNT,R3 ;GET NUMBER OF BYTES LEFT IN XFER BEQ 6$ ;IF ZERO, WE'RE DONE CMP DATCNT,#177000 ;OR IF NEGATIVE, DONE BHIS 6$ BR 2$ ;IF NOT, MORE LEFT TO DO 6$: JSR PC,S.RRES ;GET BACK REGISTERS FOR HANDLER MOV R.PB+2(R1),R4 ;SAVE NO. BYTES TRANSFERRED AS NO. REQUESTED JMP GOODRQ ;THEN LEAVE CLAIMING ALL WAS WELL ; ; ;ELABORATE PARITY CALCULATION... ;MUST MAP -1 TO -1, 0 TO 0... FUDGIT: SWAB -2(R2) CLC ROL -4(R2) ROR -6(R2) ROR -2(R2) ROL -10(R2) ROL -10(R2) ADC -4(R2) MOV -10(R2),-(SP) MOV -2(R2),-10(R2) MOV (SP)+,-2(R2) RTS PC .PAGE .SBTTL ENCRYPTION/DECRYPTION ROUTINES ;CALL VIA JSR PC,XXXXXX ;ALL REGISTERS ASSUMED AVAILABLE ;ENCODE/DECODE 512 BYTES POINTED TO BY R4 ON ENTRY ;VDUIT+4 HAS OFFSET TO UNIT NUMBER. KEY TABLE HAS KEY. ; ;FOR TESTING PURPOSES, ENCRYPT OR DECRYPT 64 BIT OBJECTS VIA A SIMPLE ;EXCLUSIVE "OR" WITH THE KEY AND THE PLAINTEXT. ;DECRYPT WITH ANOTHER ONE. ;0 XOR 1 = 1 ;ENCRYPT ;1 XOR 1 = 0 ;DECRYPT ; ;1 XOR 1 = 0 ;ENCRYPT ;0 XOR 1 = 1 ;DECRYPT ; ; SIMILARLY WHERE KEY BIT IS 0. ; ; THE ALGORITHM IS NOT VERY SECURE BUT WILL TEST THE METHOD OF PSEUDO ;DEVICES AND NEATLY MAKE IT HARD TO FIND OUT WHAT'S ON THE PSEUDO DISK ;SINCE PART OF IT IS BITMAPS, FILE HEADERS, ETC. ;ADD FURTHER BIT SWAPPING TO MAKE THINGS A LITTLE MORE OBSCURE... ENCRYP: ;ENCODE FROM NORMAL FORM JSR PC,INVTST ;BE SURE VALID KEY EXISTS ; BODY OF ENCRYPTION. JSR PC,GETKAD ;GET KEY ADDRESS INTO R0 MOV #64.,R1 ;512/8 = 64 MOV #DATBUF,R2 ;DATA ALWAYS IN "DATBUF" 1$: MOV R0,R3 ;R3 = WORKING KEY MOV #4,R4 ;4 WORDS PER GROUP 2$: MOV (R3)+,R5 ;KEY WORD XOR R5,(R2)+ ;ENCRYPT A WORD... SOB R4,2$ ;LOOP FOR 4 WORDS SOB R1,1$ ;BY 64 GROUPS OF 4 JSR PC,KSWIT ;SWAP BITS BY 1ST PART OF KEY .IF NDF,DESOUT MOV VDUIT+4,R5 ;UNIT NUMBER ADD #CIPHPW,R5 ;TEST ACCESS KEY BITB #2,@R5 ;WANT SIMPLE METHOD? BNE 4$ ;YES, SKIP CRYP16/DECR16 JSR PC,CRYP16 ;DO SOME MORE MONKEYING AROUND... 4$: .ENDC ; NOW DONE !! RTS PC DECRYP: ;DECODE TO NORMAL FORM JSR PC,INVTST ;BE SURE VALID KEY EXISTS ; BODY OF DECRYPTION JSR PC,GETKAD ;GET KEY ADDRESS INTO R0 MOV #64.,R1 ;512/8 = 64 MOV #DATBUF,R2 ;DATA ALWAYS IN "DATBUF" .IF NDF,DESOUT MOV VDUIT+4,R5 ;UNIT NUMBER ADD #CIPHPW,R5 ;TEST ACCESS KEY BITB #2,@R5 ;WANT SIMPLE METHOD? BNE 4$ ;YES, SKIP CRYP16/DECR16 JSR PC,DECR16 ;UN-MONKEY CRYP16 OPERATIONS... 4$: .ENDC JSR PC,KSWIT ;SWAP BITS BY 1ST PART OF KEY 1$: MOV R0,R3 ;R3 = WORKING KEY MOV #4,R4 ;4 WORDS PER GROUP 2$: MOV (R3)+,R5 ;KEY WORD XOR R5,(R2)+ ;DECRYPT A WORD... SOB R4,2$ ;LOOP FOR 4 WORDS SOB R1,1$ ;BY 64 GROUPS OF 4 ; NOW DONE !! RTS PC ; ;SWITCH BITS IN BLOCKS OF DATA. SWAPS ONLY BITS SET TO 1 IN KEY. ;LEAVES OTHERS ALONE. ;USES 1ST 32 BITS OF KEY FOR THE PURPOSE. KSWIT: JSR PC,S.RSAV ;R0 HAS KEY ADDR, DATBUF HAS DATA MOV #64.,R1 ;64 CODE BLOCKS PER DATA BLOCK MOV #DATBUF,R2 ;DATA AREA ADDRESS 1$: MOV @R0,R3 ;KEY PART COM R3 MOV @R2,R4 ;1ST PART-WORD MOV 6(R2),R5 ;2ND PART-WORD BIC R3,R4 BIC R3,R5 ;FORM BITS ALSO ON IN KEY COM R3 ;BACK TO ORIGINAL BIC R3,@R2 BIC R3,6(R2) ;ZERO CORRESPONDING BITS IN DATA BIS R4,6(R2) ;SWITCH BITS BIS R5,@R2 ;IN CORRESPONDING PARTS OF WORDS MOV 2(R0),R3 ;GET 2ND WORD OF KEY COM R3 MOV 2(R2),R4 ;GET 1ST PART-WORD MOV 4(R2),R5 BIC R3,R4 BIC R3,R5 ;TREAT 2ND,3RD AS WE DID 1ST,4TH ABOVE COM R3 BIC R3,2(R2) BIC R3,4(R2) BIS R4,4(R2) BIS R5,2(R2) ;SWAP BITS WHERE KEY IS ON IN OTHER PART WORDS ADD #10,R2 ;MOVE TO NEXT BLOCK OF DATA SOB R1,1$ JSR PC,S.RRES RTS PC ; BADADR: ERROR IE.SPC ; CORE TRANSFER NOT VALID JMP FINISH ; ILLBLK: ERROR IE.BLK ; BAD BLOCK NUMBER JMP FINISH .IF NDF,DESOUT ;CRYP16 AND DECR16 ; D.E.S. - LIKE ALGORITHM FOR DATA ENCRYPTION USING KEY'S LAST ;7 BYTES (NOTE 7 IS PRIME). IGNORE 1ST BYTE OF KEY. WRK: .WORD 0,0,0,0 ;WORKING "KEY" .WORD 0,0 ;SAFETY... CRYP16: JSR PC,S.RSAV ;GET ALL REGISTERS FOR HERE ;R0 IS KEY ADDRESS. MOV #64.,R5 ;64 DATA GROUPS MOV #DATBUF,R2 ;DATA STARTS HERE. 64 UNITS LONG. 100$: MOV #16.,R1 ;GO THRU 16 TIMES IN ALL CLR R4 ;1ST KEY BYTE TO USE (-1) ;SCHEDULE KEY HERE AND CALL SUB TO MUNG DATA EACH TIME. ;NOTE STACK POINTS AT CALL R0 1$: INC R4 ;BUMP KEY LOC CMP R4,#8. ;PAST MAX? BLT 2$ ;NO MOV #1,R4 ;YES, RESET TO 1 2$: MOV R4,-(SP) ;SAVE R4 OFFSET. CLR R3 ;MOVE 56 BITS = 7 BYTES ADD R0,R4 3$: MOVB (R4)+,WRK(R3) INC R3 CMP R3,#7 BHI 4$ MOV R4,-(SP) ;SAVE SUB R0,@SP ;GET NEW R4 CMP (SP)+,#7 ;SEE IF PAST END OF KEY BLOS 3$ ;IF SO KEEP COPYING MOV R0,R4 ;ELSE SET UP KEY+1 INC R4 BR 3$ ;AND START THERE 4$: ;GET HERE WHEN KEY IS COPIED. JSR PC,FUNCTI MOV (SP)+,R4 ;GET BACK R4 AS OFFSET SOB R1,1$ ;DO 16 TIMES... ADD #10,R2 ;PASS DATA SET SOB R5,100$ ;DO ALL 64 PARTS OF DATA JSR PC,S.RRES RTS PC DECR16: JSR PC,S.RSAV ;R0 IS KEY ADDRESS. MOV #64.,R5 ;64 DATA GROUPS MOV #DATBUF,R2 ;DATA STARTS HERE. 64 UNITS LONG. 100$: MOV #16.,R1 ;GO THRU 16 TIMES IN ALL ;SCHEDULE KEY HERE AND CALL SUB TO MUNG DATA EACH TIME. ;NOTE STACK POINTS AT CALL R0 ; NOTE... CYCLE BACKWARDS THROUGH KEYS FROM 2,1,7,6,5,4,3,2,1,7,6,5,... ; TO REVERSE THE ENCRYPTION CYCLE. FUNCTO MUST REVERSE THE ENCRYPTION ; DONE BY THE CORRESPONDING FUNCTI CALL. WRK WILL BE SET UP WITH THE ; SAME KEY IN THAT CASE AS FUNCTI HAD. MOV #3,R4 ;START KEY VALUE TO USE... 1$: DEC R4 ;BUMP KEY LOC DOWN TO DECODE BGT 2$ ;SEE IF PAST MIN. MOV #7,R4 ;YES, RESET TO 7 2$: MOV R4,-(SP) ;SAVE R4 OFFSET CLR R3 ;MOVE 56 BITS = 7 BYTES ADD R0,R4 ;POINT R4 AT KEY 3$: MOVB (R4)+,WRK(R3) INC R3 CMP R3,#7 ;DONE 7 BYTES? BHI 4$ MOV R4,-(SP) ;SAVE SUB R0,@SP ;GET NEW R4 CMP (SP)+,#7 ;SEE IF PAST END OF KEY BLOS 3$ ;IF SO KEEP COPYING MOV R0,R4 ;ELSE SET UP KEY+1 INC R4 BR 3$ ;AND START THERE 4$: ;GET HERE WHEN KEY IS COPIED. JSR PC,FUNCTO MOV (SP)+,R4 ;GET BACK R4 AS OFFSET SOB R1,1$ ;DO 16 TIMES... ADD #10,R2 ;PASS DATA SET SOB R5,100$ ;DO ALL 64 PARTS OF DATA JSR PC,S.RRES RTS PC FUNCTI: JSR PC,S.RSAV ;TAKE DATA POINTED AT BY R2 AND TRANSFORM IT ;FOR ENCRYPTION BY ADDING THE 1ST 32 BITS OF WRK MOD 2**32 TO R.H.S. ;AND THEN SWAPPING BITS USING BITS 33-48 OF WRK MOV (R2),R3 ;R H S LOW ORDER MOV 2(R2),R4 ADD WRK,R3 ADC R4 ADD WRK+2,R4 ;32 BIT ADD. ;R3 = L.O.; R4=H.O. ;32 BIT ADD DONE. NOW DO SWAP MOV WRK+4,R0 ;R0 = KEY MASK COM R0 MOV R3,-(SP) BIC R0,@SP ;BITS IN R3 AND KEY MOV R4,-(SP) BIC R0,@SP ;BITS IN R4 AND KEY COM R0 BIC R0,R3 BIC R0,R4 ;REMOVE THOSE BITS FROM WORDS BIS (SP)+,R3 BIS (SP)+,R4 ;PUT REVERSED ONES BACK MOV 4(R2),-(SP) MOV 6(R2),-(SP) MOV (R2),4(R2) ;REVERSE R,L MOV 2(R2),6(R2) MOV (SP)+,2(R2) MOV (SP)+,(R2) ;PUT BACK OLD OTHER HALF... ADD R3,(R2) ADC 2(R2) ADD R4,2(R2) ;ADD OTHER HALF TO OLD HALF. JSR PC,S.RRES RTS PC FUNCTO: JSR PC,S.RSAV ;TAKE DATA POINTED AT BY R2 AND TRANSFORM IT MOV 4(R2),R3 ;L.O. L.H.S. MOV 6(R2),R4 ;H.O. L.H.S. ADD WRK,R3 ADC R4 ADD WRK+2,R4 ;32 BIT ADD. ; MOV WRK+4,R0 ;R0 = KEY MASK COM R0 MOV R3,-(SP) BIC R0,@SP ;BITS IN R3 AND KEY MOV R4,-(SP) BIC R0,@SP ;BITS IN R4 AND KEY COM R0 BIC R0,R3 BIC R0,R4 ;REMOVE THOSE BITS FROM WORDS BIS (SP)+,R3 BIS (SP)+,R4 ;PUT REVERSED ONES BACK MOV 4(R2),-(SP) MOV 6(R2),-(SP) SUB R3,(R2) SBC 2(R2) ;ENCODE SWAPS, THEN ADDS. HERE SUBTRACT, SWAP. SUB R4,2(R2) ;ADD OTHER HALF TO OLD HALF. MOV (R2),4(R2) ;REVERSE R,L MOV 2(R2),6(R2) MOV (SP)+,2(R2) MOV (SP)+,(R2) ;PUT BACK OLD OTHER HALF... JSR PC,S.RRES RTS PC .ENDC .PAGE ; ; .SBTTL UTILITY SUBROUTINES GETKAD: MOV VDUIT+4,R0 ;UNIT NUMBER ASH #3,R0 ;MAP 0,1,2,3,... TO 0,10,20,30,... ADD #KEYS,R0 ;POINT R0 AT FIRST WORD OF KEY RTS PC ;BACK TO CALLER... BUFCLR: JSR PC,S.RSAV MOV #DATBUF,R0 MOV #256.,R1 ;ZERO OUT DATA BUFFER 1$: CLR (R0)+ DEC R1 BNE 1$ ;DO IT ALL... JSR PC,S.RRES ;THEN GET REGS BACK RTS PC ;AND RETURN TO CALLER INVTST: MOV VDUIT+4,R5 ;GET UNIT NO. MOV R5,R1 ADD #CIPHPW,R1 ;TEST ACCESS KEY OVER-RIDES BITB #4,@R1 ;NEVER ACCESS DISK? BNE INVPRV ;RIGHT--FAIL HIM NOW. ASH #3,R5 ;0,1,2,3,... TO 0,10,20,30,... ADD #KEYS,R5 ;POINT R5 AT KEY THIS UNIT USES MOV R5,R3 ;SAVE POINTER MOV (R5)+,R0 BIS (R5)+,R0 BIS (R5)+,R0 BIS (R5)+,R0 TST R0 BNE L1$ ;ALL 4 ZERO MEANS INVALID KEY... INVPRV: CMP (SP)+,(SP)+ ;CLEAN STACK OF TO OLD PC'S JSR PC,S.RRES JSR PC,S.RRES ;GET HANDLER'S REGS BACK ERROR IE.PRI ;DECLARE FATAL ACCESS VIOLATION. JMP FINISH ;THEN DO NEXT I/O L1$: CMP (R3)+,#-1 ;SEE IF NO ENCRYPTION... BNE 2$ CMP (R3)+,#-1 ;SEE IF NO ENCRYPTION... BNE 2$ CMP (R3)+,#-1 ;SEE IF NO ENCRYPTION... BNE 2$ CMP (R3)+,#-1 ;SEE IF NO ENCRYPTION... BNE 2$ ;NO ENCRYPTION! JUST RETURN FROM ENCRYPT OR DECRYPT AT ONCE! ;NOTE THAT ANYBODY IS ALLOWED TO READ AN UNENCRYPTED PSEUDO-DISK. ;RSX PROTECTION SCHEMES FOR VOLUME PROTECTION MAY RESTRICT ACCESS ;HOWEVER. ;DO ACCESS CHECKS IF 1 BIT IS SET IN CIPHPW + BYTE ;POINTED TO BY R1, HOWEVER, EVEN IF UNCIPHERED DISK. CLR R0 ;FLAG UNCIPHERED. BITB #1,@R1 ;ALWAYS TEST ACCESS? BNE 73$ ;YES (BUT FLAG NO CIPHERING...) 70$: TST (SP)+ ;POP LOCAL RETURN (UNCIPHERED, ACCESS OK) RTS PC ;THEN RETURN 2$: BITB #10,@R1 ;ALWAYS ACCESS OK? BNE 72$ ;YES, RETURN. 73$: ;TEST FLAG OVERRIDES NEVER-TEST FLAG IF UNCRYPTED ;ALLOW USER TO WRITE A ROUTINE TO FURTHER CHECK USER PRIVILEGES .GLOBL VDPRV ;CALLED VDPRV JSR PC,S.RSAV ;FREE ALL REGS FOR VDPRV ;ON ENTRY TO VDPRV SET HELPFUL INFORMATION INTO REGISTERS: ; R0 WILL HAVE UNIT NUMBER (0,1,2,3,...) MOV VDUIT+4,R0 ;UNIT NO. ; R1 WILL HAVE IORQ ADDRESS MOV 42(SP),R1 ;IORQ ADDRESS (WHICH MAY POINT AT ATL...) ; R2 WILL POINT AT UIT (FOR PUD ACCESS) MOV #VDUIT,R2 ;UIT ADDRESS (USABLE TO FIND PUDS FOR VD:'S) ;ALL REGISTERS MAY BE MODIFIED BY VDPRV IF DESIRED. ON RETURN, IF C BIT ;IS SET IN THE PSW, ACCESS WILL BE MADE TO FAIL. IF Z BIT IS SET, THE ;BUILT-IN UIC TEST WILL BE BYPASSED. THE ROUTINE MAY CHECK TASK NAME OR ;ANYTHING ELSE IT LIKES FOR ACCESS CONTROL. INDIVIDUAL INSTALLATIONS MAY ;MAKE THE CHECKING AS COMPREHENSIVE AS THEY NEED. ;S.RSAV AND S.RRES WILL BE AVAILABLE TO VDPRV FOR REG SAVE/RESTORE ;(OLD PC, R5,R4,R3,R2,R1,R0 ON STACK IN THAT ORDER, REGS UNCHANGED) JSR PC,VDPRV ;CALL IT BCS 40$ ;IF CS, FAIL ACCESS AT ONCE BEQ 41$ ;IF Z SET, NO UIC TEST JSR PC,S.RRES ;IF BOTH CLEAR, RESTORE REGS AND GO ON MOV R0,R5 ;IF R5=0, UNCIPHERED DISK. IF NON-0, CIPHERED. JSR PC,PRVTST ;SEE IF CALLER HAS PRIVILEGES FOR CODES... ;(REQUIRED FOR ENCRYPTED DISKS) BCS INVPRV ;IF NOT, CARRY SET AND FAIL HIM HERE. 3$: TST R5 ;WAS THE DATA CIPHERED? BEQ 70$ ;NO, RETURN HERE. 72$: RTS PC ;YES, ALLOW CIPHERING TO GO ON. 40$: JSR PC,S.RRES ;GET REGS AGAIN IF C SET BR INVPRV ;THEN CALL IT ILLEGAL ACCESS 41$: JSR PC,S.RRES ;IF Z SET BYPASS PRVTST CALL BR 3$ ;& PERMIT ACCESS (IF CARRY SET,ALREADY FAILS) ;PRIVILEGE TEST... ;CERTAIN UIC'S WILL BE DESIGNATED "PRIVILEGED" AND ABLE TO RUN THIS PSEUDO ;DISK. A LIST WILL BE KEPT INTERNAL TO THE HANDLER AND TASKS RUNNING UNDER ;ANY ACCOUNTS IN THE LIST WILL BE PERMITTED ACCESS (AS SEEN IN THE I/O REQ. ;QUEUE). ALL OTHERS WILL BE DENIED. PRVTST: MOV 26(SP),R1 ;3 OLD PC'S AND 2 RSAV'S ON STACK. GET IORQ ;ADDR WHICH WAS IN HANDLER'S R1 TST R.AT(R1) ;EXEC REQUEST? BEQ 2$ ;YES, TRY TO ALLOW IT. MOV #PRVLST,R0 ;START OF LIST OF ALLOWED UIC'S 1$: CMP (R0)+,R.UI(R1) ;THIS FROM A PERMITTED UIC? BEQ 2$ ;YES. TST -2(R0) ;NO. AT END OF LIST? BNE 1$ ;NO. KEEP LOOKING. ;TEST USER'S CODES. MOV VDUIT+4,R0 ;UNIT NO. ASH #4,R0 ;MAKE 8 WORD MULTIPLE OF IT ADD #PRVUSR,R0 ;POINT AT KEY LIST 3$: CMP (R0)+,R.UI(R1) ;A UIC MATCH? BEQ 2$ ;YES,WOW. TST -2(R0) ;END LIST? BNE 3$ ;NO,MORE SEC ;YES, FAIL ACCESS REQUEST. BR 100$ ;NOT A VALID UIC. RETURN ERROR. 2$: CLC ;VALID UIC. PERMIT IT TO WORK. ; (NOTE THAT A UIC OF 0 SHOULD PASS DUE TO ORDER OF TESTING.) 100$: RTS PC .PAGE ; ; .SBTTL HANDLER DATA STRUCTURES ; DISPATCH TABLE SYMBOLS ; CHARACTERISTICS BYTE SYMBOLS CHXXXX ; FLAGS BYTE SYMBOLS FLXXXX ; SUFFIX BYTE SYMBOLS SUXXXX ; SUBFCN CODE BYTE SYMBOLS SFXXXX ; ; 0 SPECIAL FUNCTION CHSPEC= 0 FLSPEC= 0 ; ; 1 WRITE LOGICAL CHWRI= 210 FLWRI= 142 ; ; 2 READ LOGICAL CHREA= 210 FLREA= 041 ; ; 3 ATTACH UNIT CHATT= 020 FLATT= 140 ; ; 4 DETACH UNIT CHDET= 020 FLDET= 140 ; ; 5 CONTROL REWIND CHCTL5= 210 FLCTL5= 077 SUCTL5= VDINV SFCTL5= 0 ; ; 6 CONTROL SPACE N BLOCKS CHCTL6= 0 FLCTL6= 0 SUCTL6= VDINV SFCTL6= 0 ; ; 7 CONTROL SPACE N END OF FILE CHCTL7= 0 FLCTL7= 0 SUCTL7= VDINV SFCTL7= 0 ; ; 10 LOOKUP CHLOOK= 0 FLLOOK= 0 SULOOK= VDINV SFLOOK= 0 ; ; 11 FIND CHFIND= 340 FLFIND= 340 SUFIND= 100 SF.FIN= 0 ; ; 12 PARSE CHPAR= 0 FLPAR= 0 SUPAR= VDINV SF.PAR= 0 ; ; 13 REMOVE CHREM= 340 FLREM= 340 SUREM= 100 SF.REM= 2 ; ; 14 ENTER CHENT= 340 FLENT= 340 SUENT= 100 SF.ENT= 1 ; ; 15 ACCESS READ CHACR= 340 FLACR= 341 SUACR= 0 SF.ACR= 1 ; ; 16 ACCESS READ/WRITE CHACW= 340 FLACW= 343 SUACW= 0 SF.ACW= 2 ; ; 17 ACCESS READ/WRITE/EXTEND CHACE= 340 FLACE= 347 SUACE= 0 SF.ACE= 3 ; ; 20 DE-ACCESS CHDEA= 300 FLDEA= 340 SUDEA= 0 SF.DEA= 4 ; ; 21 READ VIRTUAL CHRDV= 300 FLRDV= 341 SURDV= 0 SF.RDV= 5 ; ; 22 WRITE VIRTUAL CHWRV= 300 FLWRV= 342 SUWRV= 0 SF.WRV= 5 ; ; 23 EXTEND CHEXT= 340 FLEXT= 344 SUEXT= 0 SF.EXT= 6 ; ; 24 CREATE CHCRE= 340 FLCRE= 342 SUCRE= 0 SF.CRE= 7 ; ; 25 DELETE CHDEL= 300 FLDEL= 350 SUDEL= 0 SF.DEL= 10 ; ; 26 READ ATTRIBUTES CHRAT= 300 FLRAT= 341 SURAT= 0 SF.RAT= 11 ; ; 27 WRITE ATTRIBUTES CHWAT= 300 FLWAT= 342 SUWAT= 0 SF.WAT= 12 ; ; 30 ACP CONTROL CHACP= 140 FLACP= 200 SUACP= 0 SF.ACP= 0 ; MACRO TO CREATE A DISPATCH TABLE ENTRY. ; EACH ENTRY HAS 3 OR 4 PARTS. ; DEVICE CONTROL FUNCTION ENTRIES CONSIST OF ; A CHARACTERISTICS BYTE, A FLAGS BYTE ; AND A SUBROUTINE ENTRY POINT. ; SEND AND REQUEST FUNCTION ENTRIES CONSIST OF ; CHARACTERISTIC BYTE, FLAGS BYTE, SUFFIX ; BYTE AND SUB FUNCTION CODE BYTE. ; IF THE HIGH ORDER BIT OF THE FLAGS BYTE ; IS SET THE ENTRY IS OF THE SEND AND ; REQUEST TYPE. THE MACRO GENERATES ; THE TYPE OF ENTRY CONDITIONALLY ; .MACRO DE CHAR,FLAG,SUFF,SUBFCN .BYTE CHAR,FLAG .IF NE FLAG&200 .BYTE SUFF,SUBFCN .IFF .WORD SUFF .ENDC .ENDM ; ; DISPATCH TABLE VDDISP: .WORD BADSR ; SEND & REQUEST FAILED .WORD DOMORE ; " " SUCCEEDED DFIRST: DE CHSPEC,FLSPEC,SPCFCN DE CHWRI,FLWRI,WRITE DE CHREA,FLREA,READ DE CHATT,FLATT,VDATT DE CHDET,FLDET,VDDET DE CHCTL5,FLCTL5,SUCTL5,SFCTL5 DE CHCTL6,FLCTL6,SUCTL6,SFCTL6 DE CHCTL7,FLCTL7,SUCTL7,SFCTL7 DE CHLOOK,FLLOOK,SULOOK,SFLOOK DE CHFIND,FLFIND,SUFIND,SF.FIN DE CHPAR,FLPAR,SUPAR,SF.PAR DE CHREM,FLREM,SUREM,SF.REM DE CHENT,FLENT,SUENT,SF.ENT DE CHACR,FLACR,SUACR,SF.ACR DE CHACW,FLACW,SUACW,SF.ACW DE CHACE,FLACE,SUACE,SF.ACE DE CHDEA,FLDEA,SUDEA,SF.DEA DE CHRDV,FLRDV,SURDV,SF.RDV DE CHWRV,FLWRV,SUWRV,SF.WRV DE CHEXT,FLEXT,SUEXT,SF.EXT DE CHCRE,FLCRE,SUCRE,SF.CRE DE CHDEL,FLDEL,SUDEL,SF.DEL DE CHRAT,FLRAT,SURAT,SF.RAT DE CHWAT,FLWAT,SUWAT,SF.WAT DE CHACP,FLACP,SUACP,SF.ACP VDMXFC=30 ; MAXIMUM FUNCTION CODE VDUIT: .WORD VDDISP .BYTE MAXUNI,0 ; MAXUNI UNITS ARE SUPPORTED PER HANDLER .WORD 0,0,0 UNIT0: ..D..=0 ;GENERATE CORRECT NUMBER OF ENTRIES... .REPT MAXUNI .WORD ..D..,0,0 ..D..=..D..+1 .ENDR ; XITFLG: .WORD 0 ; EXIT FLAG IODIR: .WORD 0 ; DIRECTION OF I/O RNAADR: .WORD 0 ; REQUEST NODE ADDRESS OF TRANSFER ;LIST OF ACCOUNTS ALWAYS ALLOWED TO ACCESS THE DISKS PRVLST:: .BYTE 1,1 ;[1,1] ;(LET SYSTEM USE THIS.) .BYTE 370,1 ;[1,370] ;FILE UIC SHOULD BE ALLOWED .BYTE 3,1 ;[1,3] ;(RANDOM OTHER PRIVILEGED UIC ;TO ALLOW TESTING IN "SAFE" UIC) .BYTE 2,2 ;[2,2] ;MOUNT RUNS IN UIC [2,2]...NEED IT! .BYTE 2,1 .BYTE 1,2 .BYTE 200,1 ;[1,200] .WORD 0,0,0,0,0,0,0,0 ;OTHER SYSTEM USERS... .WORD 0,0,0 ;END OF LIST ;LISTS OF USERS' ACCOUNTS ALLOWED TO ACCESS INDIVIDUAL PSEUDO-DISKS ;8 WORDS PER UNIT ALLOCATED TO LISTS. LAST MUST BE 0. PRVUSR:: .BLKW ;ALLOW UP TO 50. MORE UIC'S VIA GLOBAL PATCH .WORD 0,0 ;0 IS END SENTINEL .END BEGIN