.
.         FILE PROTECTION ROUTINES
.
.         THIS ELEMENT PROCESSES THE PROTECT COMMAND AND CONTAINS THE
.         SUBROUTINES CALLED BY THE INPUT AND OUTPUT ROUTINES TO IMPLEMENT
.         CRYPTOGRAPHIC FILE PROTECTION.
.
.
.         (C)  Copyright 1972-1978  John Walker
.
.         This software is in the public domain
.
          AXR$
          DEFUNCT$
          FANG
.
.         PROTECT COMMAND PROCESSING
.
PROTECT*  LX        X9,CDBPC,X8         LOAD LINK TO FILE PARAMETER
          LX        X10,PBVAL,X9        LOAD FDT ADDRESS FOR THE FILE
          TNZ       PBLINK,X9           IS STRING PARAMETER PRESENT ?
          J         PROTOFF             NO.  TURN OFF PROTECT MODE
          LX        X9,PBLINK,X9        LINK TO STRING PARAMETER
          SNONZ     FDPROT,X10          SET PROTECTION MODE FOR THE FILE
          LA        A0,PBVAL,X9         LOAD LENGTH OF THE STRING
          TLE,U     A0,7                WILL BUFFER BE TWO WORDS ?
          J         ZOWK                NO.  HANDLE ZERO OR ONE WORD KEY
          DL        A0,PBSS,X9          LOAD STRING PARAMETER
PSETK     DS        A0,FDCRYK,X10       SET CRYPTOGRAPHIC KEY IN FDT
          COMPLETE  .                   COMPLETE COMMAND PROCESSING
.
ZOWK      JZ        A0,CANK             USE CANNED KEY IF ZERO LENGTH STRING
          LA        A0,PBSS,X9          LOAD ONE WORD USER KEY
          MI        A0,('MARGIN')       MIX UP THE BITS
          J         PSETK               GO SET THE KEY IN THE FDT
.
CANK      DL        A0,('NSA FT MEADE') LOAD CANNED KEY FOR IDIOTS
          J         PSETK               SET IT IN THE FDT
.
.         TURN OFF PROTECTION IF NO STRING SPECIFIED
.
PROTOFF   SZ        FDPROT,X10          CLEAR FILE PROTECTION MODE
          COMPLETE  .                   COMPLETE THE COMMAND
/.
.
.         LX,U      X1,<BLOCK BUFFER>
.         LX,U      X5,<4 WORD WORK BUFFER>
.         DL        A0,(<72 BIT KEY>)
.         LR,U      R1,<BUFFER LENGTH>
.         LMJ       X2,ENCIPHER  (OR DECIPHER)
.         <RETURN>                      X1,X2,X6,X11,A0-A5,R1,R2 DESTROYED
.
ENCIPHER* LMJ       X11,RANDOMISE       INITIALISE RANDOM NUMBER GENERATOR
          LXI,U     X1,1                LOAD INCREMENT IN BUFFER POINTER
          J         CRYPT1              ENTER ENCODING LOOP
CRYPT     LMJ       X6,RANDOM           GET NEXT RANDOM NUMBER
          XOR       A0,,X1              ENCODE A WORD
          SA        A1,MASK             USE ENCODED WORD AS MASK FOR NEXT TIME
          SA        A1,,*X1             REPLACE IT IN THE BUFFER
CRYPT1    JGD       R1,CRYPT            LOOP FOR ALL WORDS
          J         0,X2                RETURN TO CALLER
.
.
DECIPHER* LMJ       X11,RANDOMISE       INITIALISE RANDOM NUMBER GENERATOR
          LXI,U     X1,1                LOAD INCREMENT IN BUFFER POINTER
          J         DCRYPT1             ENTER DECODING LOOP
DCRYPT    LMJ       X6,RANDOM           GENERATE FIRST RANDOM NUMBER
          LA        A1,,X1              LOAD FIRST ENCODED WORD FROM BUFFER
          SA        A1,MASK             USE ENCODED DATA AS MASK FOR NEXT TIME
          XOR       A0,A1               GENERATE CLEAR DATA WORD
          SA        A1,,*X1             STORE BACK INTO THE BUFFER
DCRYPT1   JGD       R1,DCRYPT           LOOP FOR ALL WORDS IN BUFFER
          J         0,X2                RETURN TO CALL
/.
.
.         RANDOM NUMBER GENERATOR FOR ENCODING DATA
.
.         DESIGNED BY DAN DRAKE.  ADAPTED BY JOHN WALKER.
.         BASED UPON KNUTH, SECTION 3.2.
.
.         THIS ROUTINE OPERATES TWO RANDOM NUMBER GENERATORS, RAN1 AND
.         RAN2.  ON EACH CALL IT CYCLES EACH GENERATOR AND COMBINES
.         THE RESULTS USING A MLU.  THE MLU MASK IS THE XOR OF THE PREVIOUS
.         RAN1 AND RAN2.
.
.         RAN1      IS A MULTIPLICATIVE CONGRUENTIAL GENERATOR OPERATING
.                   MODULO THE LARGEST PRIME LESS THAN 2**35.  THIS GENERATES
.                   35 HIGH-QUALITY RANDOM BITS.  SINCE ONLY 35 BITS ARE
.                   GENERATED, BIT 2**35 ALWAYS COMES FROM RAN2.  THE SHIFTING
.                   OF THE RESULT SHOULD MAKE THIS LESS VULNERABLE.
.
.         RAN2      IS A MIXED CONGRUENTIAL GENERATOR FOLLOWING THE RULE:
.                   X(N+1) = X(N)*2049 + 1   (MOD 2**36)
.                   2049 PERMITS MULTIPLICATION BY SHIFTING AND ADDING,
.                   FOR SIMPLICITY IN HANDLING 36 BITS.  IT IS THE LARGEST
.                   2**N + 1 FOR WHICH THE POTENCY IS MAXIMISED.
.
.         THE FACT THAN RAN2 IS A FAIRLY BAD GENERATOR SHOULD BE
.         COMPENSATED BY THE MIXTURE WITH RAN1.
.
. CALLING SEQUENCE:
.
.         LX,U      X5,<RANDOM BUFFER>
.         LMJ       X6,RANDOM
.         <RETURN>                      A0 = RANDOM NUMBER
.
.         THE <RANDOM BUFFER> IS A FOUR-WORD BUFFER CONTAINING THE ONGOING
.         DATA FOR THE GENERATOR.  THIS BUFFER IS BUILT BY THE CALL:
.
.         LX,U      X5,<RANDOM BUFFER>
.         DL        A0,(<72 BIT KEY>)
.         LMJ       X11,RANDOMISE
.         <RETURN>
.
.
.         FORMAT OF RANDOM BUFFER
.
MASK      EQUF      0,X5                MASK FOR MLU INSTRUCTION
RAN1      EQUF      1,X5                CURRENT VALUE OF RAN1 GENERATOR
RAN2      EQUF      2,X5                CURRENT VALUE OF RAN2 GENERATOR (2 WDS)
.
RANDOM*   LR        R2,MASK             LOAD MASK TO COMBINE VALUES
          LA,S2     A3,RAN1             LOAD SHIFT COUNT
          LA        A4,RAN1             LOAD PREVIOUS RAN1 VALUE
          MI        A4,(8589934583)     MULTIPLY BY MAX PERIOD MULTIPLIER
          DI        A4,(0377777777741)  TAKE MOD GREATEST PRIME < 2**35
          SA        A5,RAN1             SAVE NEW VALUE FOR RAN1 GENERATOR
          DL        A0,RAN2             LOAD CURRENT VALUE FOR RAN2 GENERATOR
          LDSL      A0,11               MULTIPLY BY 2048 BY SHIFTING
          DA        A0,RAN2             AND ADD VALUE TO GET * 2049
          DA        A0,(1D)             ADD ONE TO GET N*2049+1
          SA        A1,RAN2+1           STORE RESULTS MOD 2**36
          MLU       A1,A5               COMBINE RESULTS OF TWO GENERATORS
          SSC       A2,,A3              SHIFT RESULT
          LA        A0,A2               LOAD RESULT FOR CALLER
          XOR       A1,A5               COMBINE OUTPUTS FOR NEXT TIME
          SA        A2,MASK             SAVE IN RUNNING MASK WORD
          J         0,X6                RETURN TO CALLER
.
.         RANDOM BUFFER SETUP SUBROUTINE
.
RANDOMISE* TG       A0,(0377777777741)  IS VALUE GREATER THAN LARGEST PRIME ?
          ANA       A0,(0377777777741)  YES.  MAKE MOD LARGEST PRIME
          JNZ       A0,$+2              IS IT EXACTLY OUR MODULUS ?
          LA        A0,('MARGIN')       YES.  GIVE HIM ANOTHER NUMBER
          SA        A0,RAN1             STORE START VALUE FOR RAN1 GENERATOR
          SZ        RAN2                CLEAR FIRST WORD OF RAN2 VALUE
          SA        A1,RAN2+1           SET START VALUE FOR RAN2 GENERATOR
          SZ        MASK                CLEAR INITIAL MLU MASK
          LMJ       X6,RANDOM           RUN THE GENERATORS 1 PASS
          J         0,X11               RETURN (MASK IS NOW SET UP)
          END