home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 12 / CD_ASCQ_12_0294.iso / news / 680 / secdrv13 / sectsr.asm < prev    next >
Assembly Source File  |  1994-01-23  |  25KB  |  1,155 lines

  1. ; TSR disk encryptor V1.3
  2.  
  3. DISKDATA STRUC
  4. DDDRV      DB ?       ;PHYSICAL DRIVE (HD)
  5. DRVLET      DB ?       ;DRIVE LETTER
  6. FIRSTCYL  DW ?       ;FIRST CYLINDER TO ENCRYPT
  7. FIRSTHD   DB ?       ;FIRST HEAD TO ENCRYPT
  8. FIRSTSEC  DB ?       ;FIRST SECTOR (BOOT SECTOR)
  9. LASTCYL   DW ?       ;LAST CYLINDER TO ENCRYPT
  10. MAXSEC      DB ?       ;NUMBER OF SECTORS ON DEVICE
  11. MAXHD      DB ?       ;NUMBER OF HEADS ON DEVICE
  12. SECSIZE   DW ?       ;BLOCK SIZE IN BYTES
  13. SERIAL      DW ?       ;DISK SERIAL NUMBER, FOR IV
  14.       DW ?       ;REST OF DISK SERIAL NUMBER
  15. ACTIVE      DB ?       ;CRYPT THIS DISK? FLAG
  16.       DB ?       ;PAD TO EVEN BOUND
  17. DISKDATA ENDS
  18.  
  19. MAXDRV=4       ;MAX HD PARTITIONS IN SAFE MODE EWS
  20.  
  21. ;; .MODEL TINY
  22. ;; .CODE
  23. _TEXT SEGMENT PARA PUBLIC 'CODE'
  24.  ASSUME CS:_TEXT,DS:_TEXT
  25.  ORG 0100h
  26. START:
  27.  MOV AX,0800h
  28.  MOV DL,0F0h
  29.  INT 13h
  30.  CMP AX,0EDCBh ;IS IT ALREADY INSTALLED?
  31.  JNE LOADTSR
  32.  MOV AH,9
  33.  MOV DX,OFFSET ALRINS
  34.  INT 21h ;PRINT ERROR AND EXIT
  35.  INT 20h
  36. LOADTSR:
  37.  MOV AH,9
  38.  MOV DX,OFFSET FKEY
  39.  INT 21h ;PRINT SIGN-ON
  40.  
  41.  MOV AX,3513h
  42.  INT 21h ;GET INT VECTOR
  43.  MOV WORD PTR[INT_JOUT+1],BX
  44.  MOV WORD PTR[INT_JOUT+3],ES
  45.  MOV WORD PTR REALBIOS,BX
  46.  MOV WORD PTR REALBIOS+2,ES
  47.  
  48.  MOV DX,OFFSET(I13_ENTRY)
  49.  MOV AX,2513h
  50.  INT 21h ;SET NEW INT VECTOR
  51.  
  52.  MOV AX,3100h
  53.  MOV DX,(END_OF_FILE-START)/16+17
  54.  INT 21h ;GO TSR
  55.  ALIGN 16
  56. TSRSTACK: ;OUR STACK GOES HERE
  57.  NOP
  58.  
  59. I13_ENTRY:
  60.  CLI
  61.  MOV WORD PTR CS:STKSEG,SS
  62.  MOV WORD PTR CS:STKOFS,SP
  63.  MOV WORD PTR CS:IV,CS
  64.  MOV SS,WORD PTR CS:IV
  65.  MOV SP,OFFSET TSRSTACK ;SETUP OUR STACK
  66.  STI
  67.  PUSH AX
  68.  PUSH BX
  69.  PUSH CX
  70.  PUSH DX
  71.  PUSH SI
  72.  PUSH DI
  73.  PUSH BP
  74.  PUSH DS
  75.  PUSH ES
  76.  PUSH CS
  77.  POP DS
  78.  
  79. ;DECIDE IF THIS REQUEST NEEDS PROCESSING
  80.  CMP AH,2 ;READ SECTOR
  81.  JE RDORWR
  82.  CMP AH,3 ;WRITE SECTOR
  83.  JE RDORWR
  84.  CMP AH,8 ;REQUEST FOR ADDRESS?
  85.  JNE TONOPROC
  86.  CMP DL,0F0h ;CORRECT DRIVE NUMBER?
  87.  JNE TONOPROC
  88.  MOV BP,SP
  89.  MOV [BP+10],OFFSET LOADDATA ;DX=DATA ADDRESS
  90.  MOV [BP+12],CS ;CX=CODE SEGMENT
  91.  MOV AX,0EDCCh; ;THIS MEANS V 1.3+ INSTALLED (V1.2- = EDCB)
  92.  JMP RETPROG
  93.  
  94. TONOPROC:
  95.  JMP NOPROC
  96. RDORWR:
  97.  MOV BYTE PTR RQTYPE,AH ;STORE REQUEST TYPE
  98.  MOV BYTE PTR NUMSEC,AL ;STORE NUMBER OF SECTORS
  99.  MOV BYTE PTR STSEC,CL    ;STORE SECTOR; MUST BE MASKED
  100.  AND BYTE PTR STSEC,00111111b ;MASK OFF HIGH 2 BITS
  101.  MOV WORD PTR CALLCX,CX ;KEEP CX FOR DISK ACCESS
  102.  MOV AH,CL        ;WE NEED TO...
  103.  MOV AL,CH        ;SWAP THESE
  104.  MOV CL,6        ;ROTATE 6 BITS...
  105.  SHR AH,CL        ;TO THE RIGHT, NOW AX CONTAINS CYLINDER
  106.  MOV BYTE PTR DRIVE,DL    ;STORE DRIVE
  107.  MOV WORD PTR STCYL,AX    ;STORE CYLINDER
  108.  MOV BYTE PTR STHD,DH    ;STORE HEAD
  109.  MOV WORD PTR BUFOS,BX    ;STORE BUFFER ADDRESS
  110.  MOV WORD PTR BUFSG,ES    ;STORE BUFFER SEGMENT
  111.  
  112.  CMP DL,1           ;FLOPPY DRIVE? EWS
  113.  JBE FLOPPY
  114. ;;; CMP BYTE PTR HDNUM,DL ;IS IT ACTIVE HARD DRIVE?
  115. ;;; JNE NOTHARD
  116.  MOV BP,OFFSET HD1   ;SEARCH DISKDATA BLOCKS
  117.  MOV CX,MAXDRV
  118. SHDLP:
  119.  CMP DL,[BP].DDDRV
  120.  JNE SHDCNT
  121.  CMP AX,[BP].FIRSTCYL
  122.  JB  SHDCNT
  123.  CMP AX,[BP].LASTCYL
  124.  JA  SHDCNT
  125.  CMP [BP].ACTIVE,1    ;ACTIVE HARD DISK PARTITION?
  126.  JE  SHDFND          ;YES
  127.  MOV BYTE PTR BADKEY,1
  128.  JMP BACKFROMBIOS     ;NO. TO RETURN NOT READY
  129. SHDCNT:
  130.  ADD BP,HD2-HD1
  131.  LOOP SHDLP
  132.  JMP NOPROC          ;NOT ACTIVE & NOT SAFE. PASS THRU
  133. SHDFND:
  134.  MOV AX,OFFSET HKEY
  135.  MOV WORD PTR KEY,AX ;SET KEY
  136.  JMP PROCRQ
  137. NOTHARD:
  138. FLOPPY:
  139.  MOV AX,OFFSET FKEY
  140.  MOV WORD PTR KEY,AX ;SET FLOPPY KEY
  141.  CMP DL,0         ;IS IT DRIVE A?
  142.  JNE NOTDRIVEA
  143.  MOV BP,OFFSET FDA   ;SET DISKDATA BLOCK
  144.  JMP PROCRQ
  145. NOTDRIVEA:
  146.  CMP DL,1         ;IS IT DRIVE B?
  147.  JNE NOTDRIVEB
  148.  MOV BP,OFFSET FDB   ;SET DISKDATA BLOCK
  149.  JMP PROCRQ
  150. NOTDRIVEB:
  151. NOPROC2:
  152.  JMP NOPROC
  153.  
  154. PROCRQ: ;RIGHT DRIVE
  155.  
  156.  MOV BYTE PTR BADKEY,0 ;CLEAR BAD KEY FLAG
  157.  
  158. ;HERE WE ENCRYPT THE DATA IF IT WAS A WRITE
  159.  CMP BYTE PTR RQTYPE,3 ;IS IT WRITE?
  160.  JNE NOENCRYPT ;IF NOT, DON'T ENCRYPT
  161.  MOV BYTE PTR ENCRYPT,1 ;SET ENCRYPT MODE
  162.  CALL CRYPTIT ;ENCRYPT THE DATA
  163.  CMP BYTE PTR BADKEY,1
  164.  JE BACKFROMBIOS ;SKIP WRITE IF BAD KEY/NOT LOGGED IN
  165.  
  166. ;HERE WE DO THE ACTUAL DISK OPERATION
  167. NOENCRYPT:
  168.  PUSHF
  169.  PUSH CS
  170.  MOV AX,OFFSET BACKFROMBIOS
  171.  PUSH AX ;HERE WE ARE FAKING AN INT
  172.  MOV AH,BYTE PTR RQTYPE
  173.  MOV AL,BYTE PTR NUMSEC
  174.  MOV CX,WORD PTR CALLCX
  175.  MOV DH,BYTE PTR STHD
  176.  MOV DL,BYTE PTR DRIVE
  177.  MOV ES,WORD PTR BUFSG
  178.  MOV BX,WORD PTR BUFOS
  179.  JMP INT_JOUT ;GO TO BIOS
  180. BACKFROMBIOS:
  181.  PUSHF
  182.  PUSH AX
  183.  
  184. ;HERE WE DECRYPT THE DATA
  185.  MOV BYTE PTR ENCRYPT,0 ;SET DECRYPT MODE
  186.  CALL CRYPTIT ;DECRYPT THE DATA
  187.  
  188. ;HERE WE RETURN TO THE CALLING PROGRAM
  189.  POP AX ;INT RETURN CODE
  190.  POP BX ;FLAGS
  191.  
  192.  CMP BYTE PTR BADKEY,1 ;RETURN FAKE ERROR?
  193.  JNE NOERRRET
  194.  OR BL,1      ;SET CARRY IF KEY BAD
  195.  MOV AH,80h   ;SIMULATE NO DISK PRESENT ERROR
  196.  
  197. NOERRRET:
  198.  MOV ES,WORD PTR STKSEG
  199.  MOV SI,WORD PTR STKOFS
  200.  MOV ES:[SI+4],BX ;PUT NEW FLAGS WHERE IRET WILL RECALL THEM
  201.  
  202. RETPROG:
  203.  POP ES
  204.  POP DS
  205.  POP BP
  206.  POP DI
  207.  POP SI
  208.  POP DX
  209.  POP CX
  210.  POP BX
  211.  CLI
  212.  MOV SS,WORD PTR CS:STKSEG
  213.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  214.  STI
  215.  IRET ;RETURN TO PROGRAM, LOADING MODIFIED FLAGS
  216.  
  217. NOPROC: ;REQUESTS NOT PROCESSED JUMP HERE
  218.  POP ES
  219.  POP DS
  220.  POP BP
  221.  POP DI
  222.  POP SI
  223.  POP DX
  224.  POP CX
  225.  POP BX
  226.  POP AX
  227.  CLI
  228.  MOV SS,WORD PTR CS:STKSEG
  229.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  230.  STI
  231.  
  232. INT_JOUT:
  233.  DB 0EAh,00,00,00,00 ;JMP FAR
  234.  
  235. CRYPTIT: ;THIS ENCRYPTS OR DECRYPTS THE BUFFER
  236.  MOV AL,BYTE PTR NUMSEC
  237.  MOV BYTE PTR SECLFT,AL ;LOAD SECTOR COUNTER
  238.  MOV AX,WORD PTR STCYL
  239.  MOV WORD PTR CURCYL,AX ;LOAD CURRENT CYLINDER
  240.  MOV AL,BYTE PTR STHD
  241.  MOV BYTE PTR CURHD,AL    ;LOAD CURRENT HEAD
  242.  MOV AL,BYTE PTR STSEC
  243.  MOV BYTE PTR CURSEC,AL ;LOAD CURRENT SECTOR
  244.  MOV AX,WORD PTR BUFOS
  245.  MOV WORD PTR BUFPS,AX    ;LOAD BUFFER POINTER
  246.  
  247. CRYPTLOOP:
  248.  CMP BYTE PTR SECLFT,0
  249.  JE DONECRYPT ;CHECK FOR LAST SECTOR
  250.  
  251.  MOV AX,WORD PTR CURCYL
  252.  CMP AX,[BP].FIRSTCYL
  253.  JB DONTCRYPTSEC
  254.  JNE NOTBOOTSEC
  255.  
  256.  MOV AL,BYTE PTR CURHD
  257.  CMP AL,[BP].FIRSTHD
  258.  JB DONTCRYPTSEC
  259.  JNE NOTBOOTSEC
  260.  
  261.  MOV AL,BYTE PTR CURSEC
  262.  CMP AL,[BP].FIRSTSEC
  263. ;DO WE NEED A JB HERE?
  264.  JNE NOTBOOTSEC
  265.  
  266.  CALL LOADBS ;LOAD DATA FROM BOOT SECTOR
  267.  JMP DONTCRYPTSEC
  268.  
  269. NOTBOOTSEC:
  270.  MOV AX,WORD PTR CURCYL
  271.  CMP AX,[BP].LASTCYL
  272.  JA DONTCRYPTSEC
  273.  
  274.  CMP [BP].ACTIVE,1
  275.  JE DOCRYPTSEC      ;CHECK ACTIVE FLAG
  276.  CMP BYTE PTR DRIVE,1
  277.  JBE DONTCRYPTSEC
  278.  MOV BYTE PTR BADKEY,1
  279.  JMP DONTCRYPTSEC
  280. DOCRYPTSEC:
  281.  CALL CRYPTSEC ;ENCRYPT CURRENT SECTOR
  282. DONTCRYPTSEC:
  283.  CALL NEXTSEC  ;GO ON TO NEXT SECTOR
  284.  JMP CRYPTLOOP       ;LOOP
  285. DONECRYPT: RET
  286.  
  287. CRYPTSEC: ;HERE WE CRYPT ONE SECTOR
  288. ;SET UP IV
  289.  MOV AX,WORD PTR CURCYL
  290.  MOV WORD PTR IV,AX
  291.  MOV AL,BYTE PTR CURHD
  292.  MOV BYTE PTR IV+2,AL
  293.  MOV AL,BYTE PTR CURSEC
  294.  MOV BYTE PTR IV+3,AL
  295.  MOV AX,[BP].SERIAL
  296.  MOV WORD PTR IV+4,AX
  297.  MOV AX,[BP].SERIAL+2
  298.  MOV WORD PTR IV+6,AX ;SET UP IV
  299.  
  300. ;PRE-ENCRYPT IV
  301.  MOV AX,1  ;ACTUALLY ZERO BLOCKS, WILL JUST PRE-ENCRYPT IV
  302.  PUSH AX   ;STORE NUMBER OF BLOCKS
  303.  SUB SP,8 ;PRETEND TO PUSH PLAINTEXT/CIPHERTEXT ADDRESSES
  304.  MOV AX,WORD PTR KEY
  305.  PUSH CS
  306.  PUSH AX
  307.  MOV AX,OFFSET IV
  308.  PUSH CS
  309.  PUSH AX
  310.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  311.  CALL _IDEACFB
  312.  ADD SP,20 ;REMOVE EXTRA WORD
  313.  
  314. ;ENCRYPT/DECRYPT THE BLOCK
  315.  MOV AX,[BP].SECSIZE
  316.  MOV CL,3
  317.  SHR AX,CL ;SECSIZE/8
  318.  INC AX    ;ONE BLOCK (IV) NOT USED
  319.  PUSH AX   ;STORE NUMBER OF BLOCKS
  320.  MOV AX,WORD PTR BUFSG
  321.  MOV BX,WORD PTR BUFPS
  322.  PUSH AX
  323.  PUSH BX
  324.  PUSH AX
  325.  PUSH BX
  326.  MOV AX,WORD PTR KEY
  327.  PUSH CS
  328.  PUSH AX
  329.  MOV AX,OFFSET IV
  330.  PUSH CS
  331.  PUSH AX
  332.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  333.  CMP BYTE PTR ENCRYPT,1
  334.  JNE DECRYPT
  335.  CALL _IDEACFB
  336.  JMP DONE_CRYPTSEC
  337. DECRYPT:
  338.  CALL _IDEACFBX
  339. DONE_CRYPTSEC:
  340. ; ADD SP,18
  341.  ADD SP,20 ;REMOVE EXTRA WORD
  342.  RET
  343.  
  344. NEXTSEC: ;INCREMENT HEAD, SECTOR, CYLINDER AS NEEDED TO GO TO NEXT SECTOR
  345.  MOV AX,[BP].SECSIZE
  346.  ADD WORD PTR BUFPS,AX ;GO TO NEXT BLOCK IN MEMORY
  347.  DEC BYTE PTR SECLFT   ;COUNT DOWN SECTORS LEFT
  348.  INC BYTE PTR CURSEC   ;INCREMENT SECTOR
  349.  MOV AL,BYTE PTR CURSEC
  350.  CMP AL,[BP].MAXSEC
  351.  JBE DONE_COUNT
  352.  MOV BYTE PTR CURSEC,1 ;RESET SECTOR
  353.  INC BYTE PTR CURHD    ;INCREMENT HEAD
  354.  MOV AL,BYTE PTR CURHD
  355.  CMP AL,[BP].MAXHD
  356.  JB DONE_COUNT
  357.  MOV BYTE PTR CURHD,0  ;RESET HEAD
  358.  INC WORD PTR CURCYL   ;THEN INCREMENT CYLINDER
  359. DONE_COUNT: RET
  360.  
  361. LOADBS:
  362.  CMP BYTE PTR DRIVE,1
  363.  JA IGNOREBS ;DON'T ALTER PARAMS FOR HARD DRIVE
  364.  MOV [BP].ACTIVE,0 ;DEFAULT OFF
  365.  MOV ES,WORD PTR BUFSG
  366.  MOV SI,WORD PTR BUFPS ;GET ACCESS TO BUFFER
  367.  CMP WORD PTR ES:[SI+510],0AA55h ;CHECK FOR BOOT-RECORD SIGNATURE
  368.  JNE IGNOREBS ;BAILOUT IF BOOT SECTOR LOOKS BAD
  369.  CMP WORD PTR ES:[SI+3],'RC'
  370.  JNE NOTCRYPT
  371.  CMP WORD PTR ES:[SI+5],'PY'
  372.  JNE NOTCRYPT
  373.  MOV AX,WORD PTR FKEYCHK
  374.  CMP WORD PTR ES:[SI+7],AX
  375.  JNE NOTGOODKEY
  376.  MOV AX,WORD PTR FKEYCHK+2
  377.  CMP WORD PTR ES:[SI+9],AX
  378.  JNE NOTGOODKEY
  379.  JMP GOODKEY
  380. NOTGOODKEY:
  381.  MOV BYTE PTR BADKEY,1
  382.  JMP NOTCRYPT
  383. GOODKEY:
  384.  MOV [BP].ACTIVE,1 ;TURN ON ENCRYPTION
  385. NOTCRYPT:
  386.  MOV AL,ES:[SI+18h]
  387.  MOV [BP].MAXSEC,AL ;STORE MAX SECTOR
  388.  MOV AL,ES:[SI+1Ah]
  389.  MOV [BP].MAXHD,AL  ;STORE MAX HEAD
  390.  MOV AX,ES:[SI+0Bh]
  391.  MOV [BP].SECSIZE,AX ;STORE BYTES PER SECTOR
  392.  MOV AX,ES:[SI+27h]
  393.  MOV [BP].SERIAL,AX  ;STORE FIRST WORD OF SERIAL NUMBER
  394.  MOV AX,ES:[SI+29h]
  395.  MOV [BP].SERIAL+2,AX ;STORE SECOND WORD OF SERIAL NUMBER
  396. IGNOREBS:
  397.  RET
  398.  
  399. ;VARIABLES HERE WILL BE LOADED BY LOGIN
  400.     ALIGN 4
  401. LOADDATA:
  402. TSRVER    DB '1300'            ;VERSION FOR CHECK
  403. REALBIOS LABEL DWORD
  404.     DW 0,0
  405. FKEYCHK:DW 2 DUP (0ffffh)
  406. FKEY:    DB 13,10,'Secure Drive Version 1.3',13,10
  407.     DB 'TSR Installed',13,10,'$'
  408. ALRINS: DB 13,10,'Secure Drive Version 1.3',13,10
  409.     DB 'TSR already resident',13,10,'$'
  410.     DB (104-($-FKEY)) DUP (0aah)      ;FLOPPY ENCRYPTION KEY
  411. FKEYV10 DB 0
  412.     DB "PPP"              ;PAD FOR ALIGNMENT
  413. HKEYCHK:DW 2 DUP (0ffffh)
  414. HKEY:    DB 104 DUP (0bbh)          ;HARD DRIVE ENCRYPTION KEY
  415. HKEYV10 DB 0
  416.     DB "PPP"              ;PAD FOR ALIGNMENT
  417. FDA:    DISKDATA <0,'A',0,0,1,0FFFFh,18,2,512,0,0,0,'P'>
  418. FDB:    DISKDATA <0,'B',0,0,1,0FFFFh,18,2,512,0,0,0,'P'>
  419. HD1:    DISKDATA <0,'Z',0FFFFh,0,0,0,0,0,512,0,0,0,'P'>
  420. HD2    LABEL BYTE
  421.     REPT MAXDRV-1
  422.     DISKDATA <0,'Z',0FFFFh,0,0,0,0,0,512,0,0,0,'P'>
  423.     ENDM
  424.  
  425.     ALIGN 4
  426. ;VARIABLES HERE STAY PUT
  427. STKSEG: DW ? ;SEGMENT OF USER STACK
  428. STKOFS: DW ? ;OFFSET OF USER STACK
  429.  
  430. RQTYPE: DB ? ;REQUEST TYPE, AH FROM CALL
  431. DRIVE:    DB ? ;DRIVE FROM CALL
  432. NUMSEC: DB ? ;NUMBER OF SECTORS TO READ (AL FROM CALL)
  433. SECLFT: DB ? ;NUMBER OF SECTORS LEFT TO PROCESS
  434. CALLCX: DW ? ;ORIGINAL CX
  435. KEY:    DW ? ;CURRENTLY SELECTED KEY
  436. BADKEY: DB ? ;KEY BAD FLAG
  437.  
  438. STCYL:    DW ? ;START CYLINDER FROM CALL
  439. CURCYL: DW ? ;CURRENT CYLINDER BEING PROCESSED
  440.  
  441. STSEC:    DB ? ;START SECTOR FROM CALL
  442. CURSEC: DB ? ;CURRENT SECTOR BEING PROCESSED
  443.  
  444. STHD:    DB ? ;START HEAD FROM CALL
  445. CURHD:    DB ? ;CURRENT HEAD BEING PROCESSED
  446.  
  447. BUFOS:    DW ? ;OFFSET OF TARGET BUFFER
  448. BUFPS:    DW ? ;CURRENT POSITION WITHIN BUFFER
  449. BUFSG:    DW ? ;SEGMENT OF TARGET BUFFER
  450.  
  451. ENCRYPT: DB ? ;1 FOR ENCRYPT, 0 FOR DECRYPT
  452. IV:  DB 8 DUP (?)   ;IV FOR CFB
  453.  
  454. ; Copyright (c) 1993 Colin Plumb.  This code may be freely
  455. ; distributed under the terms of the GNU General Public Licence.
  456.  
  457. ; A core operation in IDEA is multiplication modulo 65537.
  458. ; The valid inputs, 1 through 66636 inclusive are represented in
  459. ; 16-bit registers modulo 65536.  I.e. a value of 0 means 65536,
  460. ; or -1.  Thus, we need to test for that specially.  -x, modulo
  461. ; 65537, is 65537-x = 1-x.
  462. ; For any other number, represent the product as a*65536+b.  Since
  463. ; 65536 = -1 (mod 65537), this is the same number as b-a.  Should
  464. ; this result be negautive (generate a borrow), -n mod 65537 = 1-n
  465. ; mod 65536.  Or in other words, if you add the borrow bit back on,
  466. ; you get the right answer.
  467.  
  468. ; This is what the assembly code does.    It forms a zero, and adds
  469. ; that on with carry.
  470.  
  471. ; Another useful optimisation takes advantage of the fact that
  472. ; a and b are equal only if the answer is congruent to 0 mod 65537.
  473. ; Since 65537 is prime, this happens only if one of the inputs is
  474. ; congruent to 0 mod 65537.  Since the inputs are all less than 65537,
  475. ; this means it must have been zero.
  476.  
  477. ; The code below tests for a zero result of the subtraction, and if
  478. ; one arises, it branches out of line to figure out what happened.
  479.  
  480.  
  481. ; This code implemets the IDEA encryption algorithm.
  482. ; It follows in pseudo-C, where the * operator operates
  483. ; modulo 65537, as Idea needs.    (If you don't understand,
  484. ; learn IDEA better.)
  485.  
  486. ; IDEA is works on 16-bit units.  If you're processing bytes,
  487. ; it's defined to be big-endian, so an Intel machine needs to
  488. ; swap the bytes around.
  489.  
  490. ; void Idea(u_int16 *in, u_int16 *out, u_int16 *key)
  491. ; {
  492. ;     register u+int16 x0, x1, x2, x3, s1, s2, round;
  493. ;
  494. ;     x0 = *in++;  x1 = *in++;  x2 = *in++;    x3 = *in;
  495. ;
  496. ;     for (round = 0; round < 8; round++) {
  497. ;         x0 *= *key++;
  498. ;         x1 += *key++;
  499. ;         x2 += *key++;
  500. ;         x3 *= *key++;
  501. ;
  502. ;         s1  = x1;  s2    = x2;
  503. ;         x2 ^= x0;  x1 ^= x3;
  504. ;
  505. ;         x2 *= *key++;
  506. ;         x1 += x2;
  507. ;         x1 *= *key++;
  508. ;         x2 += x1;
  509. ;
  510. ;         x0 ^= x1;  x3 ^= x2;
  511. ;         x1 ^= s2;  x2 ^= s1;
  512. ;     }
  513. ;     *out++ = x0 * *key++;
  514. ;     *out++ = x2 + *key++;          /* Yes, this is x2, not x1 */
  515. ;     *out++ = x1 + *key++;
  516. ;     *out    = x3 * *key;
  517. ; }
  518.  
  519. ; ds:si points to key, ax, dx are temps, args in bx, cx, di, bp
  520. ; Trashes *all* registers.  direction flag must be clear.
  521. ; Leaves es zero.
  522.  
  523. ; Since there is no spare register to hold the loop count, I make
  524. ; clever use of the stack, pushing the start of the loop several
  525. ; times and using a ret instruction to do the return.
  526.  
  527. ; Annoyingly, lods is fastest on 8086's, but other techniques are
  528. ; best on 386's.  Well, that's what the manual says, but real
  529. ; life is different.  USELODS wins on a 386SX, at least.
  530. ; Leave it set for all platforms.
  531.  
  532. USELODS        equ      1
  533.  
  534. ; bp must be x0 for some of the code below to work
  535. x0      equ         bp
  536. x1      equ         bx
  537. x2      equ         cx
  538. x3      equ         di
  539. ; di must be x3 for some of the code below to work
  540.  
  541. ;; Now, this is rather interesting.  We test for zero arguments
  542. ;; after the multiply.    Assuming random inputs, one or both are
  543. ;; zero (2^17-1)/2^32, or approximately 1/32786 of the time.
  544. ;; Encryption in any feedback mode produces essentially random
  545. ;; inputs, so average-case analysis is okay.  While we don't
  546. ;; want the out-of-line code to waste time, it is not worth
  547. ;; slowing down the in-line case to speed it up.
  548. ;;
  549. ;; Basically, we start inverting the source x, and if that was 0,
  550. ;; we use the inverse of the key instead.
  551.  
  552. Core1Z:
  553.     neg       x0
  554.     jnz       Core1Za
  555. if USELODS
  556.     sub       x0,[si-2]
  557. else
  558.     sub       x0,[si]
  559. endif
  560. Core1Za:
  561.     inc       x0
  562.     jmp       Core1done
  563. Core2Z:
  564.     neg       x3
  565.     jnz       Core2Za
  566. if USELODS
  567.     sub       x3,[si-2]
  568. else
  569.     sub       x3,[si+6]
  570. endif
  571. Core2Za:
  572.     inc       x3
  573.     jmp       Core2done
  574. Core3Z:
  575.     neg       x2
  576.     jnz       Core3Za
  577. if USELODS
  578.     sub       x2,[si-2]
  579. else
  580.     sub       x2,[si+8]
  581. endif
  582. Core3Za:
  583.     inc       x2
  584.     jmp       Core3done
  585. Core4Z:
  586.     neg       x1
  587.     jnz       Core4Za
  588. if USELODS
  589.     sub       x1,[si-2]
  590. else
  591.     sub       x1,[si+10]
  592. endif
  593. Core4Za:
  594.     inc       x1
  595.     jmp       Core4done
  596.  
  597. ; We need a constant 0 that we can move into a register without affecting
  598. ; the carry flag (as the classic xor ax,ax is wont to do), so we use the
  599. ; es register for a constant 0 source.    This is okay even in protected
  600. ; mode.  (I *told* you this was tricky code!)
  601.  
  602. ; BTW, since you wanted to know, this is 8 + 78*4 + 16 = 336 instructions.
  603.  
  604. Core        proc    near
  605.     xor       ax,ax
  606.     mov       es,ax
  607.     mov       ax,OFFSET Finish
  608.     push        ax
  609.     mov       ax,OFFSET Coreloop
  610.     push        ax          ; Loop 3 times, then return
  611.     push        ax
  612.     push        ax
  613.  
  614. Coreloop:
  615. if USELODS
  616.     lodsw
  617. else
  618.     mov       ax,[si]          ; x0 *= *key++
  619. endif
  620.     mul       x0
  621.     sub       ax,dx
  622.     jz      Core1Z
  623.     mov       x0,es
  624.     adc       x0,ax
  625. Core1done:
  626.  
  627. if USELODS
  628.     lodsw
  629.     add       x1,ax
  630.     lodsw
  631.     add       x2,ax
  632. else
  633.     add       x1,[si+2]        ; x1 += *key++
  634.     add       x2,[si+4]        ; x2 += *key++
  635. endif
  636.  
  637. if USELODS
  638.     lodsw
  639. else
  640.     mov       ax,[si+6]        ; x3 += *key++
  641. endif
  642.     mul       x3
  643.     sub       ax,dx
  644.     jz      Core2Z
  645.     mov       x3,es
  646.     adc       x3,ax
  647. Core2done:
  648.  
  649.     push        x1            ; s1 = x1
  650.     push        x2              ; s2 = x2
  651.  
  652.     xor       x1,x3        ; x1 ^= x3
  653.     xor       x2,x0        ; x2 ^= x0
  654.  
  655. if USELODS
  656.     lodsw
  657. else
  658.     mov       ax,[si+8]        ; x2 *= *key++
  659. endif
  660.     mul       x2
  661.     sub       ax,dx
  662.     jz      Core3Z
  663.     mov       x2,es
  664.     adc       x2,ax
  665. Core3done:
  666.  
  667.     add       x1,x2        ; x1 += x2
  668.  
  669. if USELODS
  670.     lodsw
  671. else
  672.     mov       ax,[si+10]         ; x1 *= *key++
  673. endif
  674.     mul       x1
  675.     sub       ax,dx
  676.     jz      Core4Z
  677.     mov       x1,es
  678.     adc       x1,ax
  679. Core4done:
  680.  
  681.     add       x2,x1        ; x2 += x1
  682.  
  683.     xor       x0,x1        ; x0 ^= x1
  684.     xor       x3,x2        ; x3 ^= x2
  685.  
  686.     pop       dx
  687.     xor       x1,dx        ; x1 ^= s2
  688.     pop       dx
  689.     xor       x2,dx        ; x2 ^= s1
  690.  
  691. ; Second unrolling of loop
  692. if USELODS
  693.     lodsw
  694. else
  695.     mov    ax,[si+12]        ; x0 *= *key++
  696. endif
  697.     mul       x0
  698.     sub       ax,dx
  699.     jz      Core5Z
  700.     mov       x0,es
  701.     adc       x0,ax
  702. Core5done:
  703.  
  704. if USELODS
  705.     lodsw
  706.     add       x1,ax
  707.     lodsw
  708.     add       x2,ax
  709. else
  710.     add       x1,[si+14]         ; x1 += *key++
  711.     add       x2,[si+16]         ; x2 += *key++
  712. endif
  713.  
  714. if USELODS
  715.     lodsw
  716. else
  717.     mov       ax,[si+18]         ; x3 *= *key++
  718. endif
  719.     mul       x3
  720.     sub       ax,dx
  721.     jz      Core6Z
  722.     mov       x3,es
  723.     adc       x3,ax
  724. Core6done:
  725.  
  726.     push        x1             ; s1 = x1
  727.     push        x2              ; s2 = x2
  728.  
  729.     xor       x1,x3        ; x1 ^= x3
  730.     xor       x2,x0        ; x2 ^= x0
  731.  
  732. if USELODS
  733.     lodsw
  734. else
  735.     mov       ax,[si+20]         ; x2 *= *key++
  736. endif
  737.     mul       x2
  738.     sub       ax,dx
  739.     jz      Core7Z
  740.     mov       x2,es
  741.     adc       x2,ax
  742. Core7done:
  743.  
  744.     add       x1,x2        ; x1 += x2
  745.  
  746. if USELODS
  747.     lodsw
  748. else
  749.     mov       ax,[si+22]         ; x1 *= *key++
  750. endif
  751.     mul       x1
  752.     sub       ax,dx
  753.     jz      Core8Z
  754.     mov       x1,es
  755.     adc       x1,ax
  756. Core8done:
  757.  
  758.     add       x2,x1        ; x2 += x1
  759.  
  760.     xor       x0,x1        ; x0 ^= x1
  761.     xor       x3,x2        ; x3 ^= x2
  762.  
  763.     pop       dx
  764.     xor       x1,dx        ; x1 ^= s2
  765.     pop       dx
  766.     xor       x2,dx        ; x2 ^= s1
  767.  
  768. ife USELODS
  769.     lea       si,[si+24]
  770. endif
  771.  
  772.     ret       ; Used as a loop instruction!
  773.  
  774. Core5Z:
  775.     neg       x0
  776.     jnz       Core5Za
  777. if USELODS
  778.     sub       x0,[si-2]
  779. else
  780.     sub       x0,[si+12]
  781. endif
  782. Core5Za:
  783.     inc       x0
  784.     jmp       Core5done
  785. Core6Z:
  786.     neg       x3
  787.     jnz       Core6Za
  788. if USELODS
  789.     sub       x3,[si-2]
  790. else
  791.     sub       x3,[si+18]
  792. endif
  793. Core6Za:
  794.     inc       x3
  795.     jmp       Core6done
  796. Core7Z:
  797.     neg       x2
  798.     jnz       Core7Za
  799. if USELODS
  800.     sub       x2,[si-2]
  801. else
  802.     sub       x2,[si+20]
  803. endif
  804. Core7Za:
  805.     inc       x2
  806.     jmp       Core7done
  807. Core8Z:
  808.     neg       x1
  809.     jnz       Core8Za
  810. if USELODS
  811.     sub       x1,[si-2]
  812. else
  813.     sub       x1,[si+22]
  814. endif
  815. Core8Za:
  816.     inc       x1
  817.     jmp       Core8done
  818. Core9Z:
  819.     neg       x0
  820.     jnz       Core9Za
  821. if USELODS
  822.     sub       x0,[si-2]
  823. else
  824.     sub       x0,[si]
  825. endif
  826. Core9Za:
  827.     inc       x0
  828.     jmp       Core9done
  829. ; Special: compute into dx (zero on entry)
  830. Core10Z:
  831.     sub       dx,x3
  832.     jnz       Core10Za
  833. if USELODS
  834.     sub       dx,[si-2]
  835. else
  836.     sub       dx,[si+6]
  837. endif
  838. Core10Za:
  839.     inc       dx
  840. ;     jmp        Core10done
  841.     ret
  842.  
  843.  
  844. Finish:
  845. if USELODS
  846.     lodsw
  847. else
  848.     mov       ax,[si]          ; x0 *= *key++
  849. endif
  850.     mul       x0
  851.     sub       ax,dx
  852.     jz      Core9Z
  853.     mov       x0,es
  854.     adc       x0,ax
  855. Core9done:
  856.  
  857.     xchg        x1,x2
  858. if USELODS
  859.     lodsw
  860.     add       x1,ax
  861.     lodsw
  862.     add       x2,ax
  863. else
  864.     add       x1,[si+2]        ; x1 += *key++
  865.     add       x2,[si+4]       ; x2 += *key++
  866. endif
  867.  
  868. ; This is special: compute into dx, not x3
  869. if USELODS
  870.     lodsw
  871. else
  872.     mov       ax,[si+6]        ; x3 *= *key++
  873. endif
  874.     mul       x3
  875.     sub       ax,dx
  876.     mov       dx,es
  877.     jz      Core10Z
  878.     adc       dx,ax
  879. Core10done:
  880.  
  881.     ret
  882.  
  883.     endp
  884.  
  885. ; Okay, the basic plan for the CFB kernel is
  886. ; get x0,x1,x2,x3
  887. ; get key pointer
  888. ; call core
  889. ; get buffer pointers
  890. ;Loop:
  891. ; lodsw
  892. ; xor         ax,x0
  893. ; mov    x0,ax
  894. ; stosw
  895. ; lodsw
  896. ; xor         ax,x1
  897. ; mov         x0,ax
  898. ; stosw
  899. ; lodsw
  900. ; xor         ax,x2
  901. ; mov         x0,ax
  902. ; stosw
  903. ; lodsw
  904. ; xor         ax,x3
  905. ; mov         x3,ax
  906. ; stosw
  907. ; push buffer pointers
  908. ; get key pointer
  909. ; call          core
  910. ; pop buffer pointers
  911. ; loop
  912. ; lodsw/xor/etc.
  913. ;
  914. ;
  915. ; This function is designed to go in the middle of a byte-granularity
  916. ; CFB engine.  It performs "len" encryptions of the IV, encrypting
  917. ; 8*(len-1) bytes from the source to the destination.  The idea is
  918. ; that you first xor any odd leading bytes, then call this function,
  919. ; then xor up to 8 trailing bytes.
  920.  
  921. ; The main loop in this is 38 instructions, plus the 336 for the core
  922. ; makes 374 total.  That's 46.75 instructions per byte.
  923. ; (It's the same for IdeaCFBx)
  924.  
  925. ; IV, key, plain, cipher, len
  926. ;     public        _IdeaCFB
  927. ;_IdeaCFB proc far     ; Args are at [sp+4]
  928. _IDEACFB:
  929.     cld
  930.     push        bp
  931.     push        si
  932.     push        di
  933.     push        ds          ; 8 more words here, so args are at [sp+12]
  934. ; To be precise, IV is at 12, key at 16, plain at 20,
  935. ; cipher at 24 and len at 28
  936.     mov       bp,sp
  937.     lds       si,[bp+12]         ; IV
  938. ; Load and byte-swap IV
  939.     mov       ax,[si]
  940.     xchg        ah,al
  941.     mov       x1,[si+2]
  942.     mov       x2,[si+4]
  943.     xchg        bh,bl
  944.     xchg        ch,cl
  945.     mov       dx,[si+6]
  946.     xchg        dh,dl
  947.  
  948.     lds       si,[bp+16]         ; Key
  949.     mov       x0,ax
  950.     mov       x3,dx
  951.  
  952.     call        Core
  953. IdeaCFBLoop:
  954. ;     mov        ax,x0
  955. ;     mov        bp,sp
  956. ;     dec        WORD PTR [bp+28]        ; Decrement count
  957. ;     jz       IdeaCFBEnd
  958. ;     lds        si,[bp+20]
  959. ;     les        di,[bp+24]
  960. ;     mov        x0,ax
  961. ; Alternate code: (which is faster?  Two moves or three segment overrides?)
  962.     mov       si,sp
  963.     dec       WORD PTR ss:[si+28]
  964.     jz      IdeaCFBEnd
  965.     les       di,ss:[si+24]
  966.     lds       si,ss:[si+20]
  967.  
  968.     lodsw
  969.     xchg        ah,al
  970.     xor       ax,x0
  971.     mov       x0,ax
  972.     xchg        ah,al
  973.     stosw
  974.     lodsw
  975.     xchg        ah,al
  976.     xor       ax,x1
  977.     mov       x1,ax
  978.     xchg        ah,al
  979.     stosw
  980.     lodsw
  981.     xchg        ah,al
  982.     xor       ax,x2
  983.     mov       x2,ax
  984.     xchg        ah,al
  985.     stosw
  986.     lodsw
  987.     xchg        ah,al
  988.     xor       ax,dx
  989.     mov       dx,ax
  990.     xchg        ah,al
  991.     stosw
  992.  
  993. ;     mov        ax,x0
  994. ;     mov        bp,sp
  995. ;     mov        [bp+20],si          ; Save source offset
  996. ;     mov        [bp+24],di          ; Save destination offset
  997. ;     lds        si,[bp+16]          ; Key
  998. ;     mov        x0,ax         ; Get x0 in place for another iteration
  999. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  1000.     mov       ax,si
  1001.     mov       si,sp
  1002.     mov       ss:[si+20],ax
  1003.     mov       ss:[si+24],di
  1004.     lds       si,ss:[si+16]
  1005.  
  1006.     mov       x3,dx        ; Get x3 in place
  1007.     mov       ax,OFFSET IdeaCFBLoop
  1008.     push        ax
  1009.     jmp       Core
  1010.  
  1011. IdeaCFBEnd:
  1012. ;     lds        si,[bp+12]
  1013.     lds       di,ss:[si+12]    ; Get IV for writing back
  1014.  
  1015.     mov       ax,x0
  1016.     xchg        ah,al
  1017.     mov       [di],ax          ; Use stosw?
  1018.     xchg        bh,bl
  1019.     xchg        ch,cl
  1020.     mov       [di+2],x1
  1021.     mov       [di+4],x2
  1022.     xchg        dh,dl
  1023.     mov       [di+6],dx
  1024.  
  1025.     pop       ds
  1026.     pop       di
  1027.     pop       si
  1028.     pop       bp
  1029.  
  1030.     ret
  1031.  
  1032.     endp
  1033.  
  1034. ; This decoding step is similar, except that instead of
  1035. ;     lods
  1036. ;     xor        x0,ax
  1037. ;     mov        ax,x0
  1038. ;      stos
  1039. ; the feedback step is
  1040. ;     lods
  1041. ;     xchg         x0,ax
  1042. ;     xor        ax,x0
  1043. ;     stos
  1044.  
  1045. ; IV, key, cipher, plain, len
  1046. ;     public        _IdeaCFBx
  1047. ;_IdeaCFBx proc far      ; Args are at [sp+4]
  1048. _IDEACFBX:
  1049.     cld
  1050.     push        bp
  1051.     push        si
  1052.     push        di
  1053.     push        ds          ; 8 more words here, so args are at [sp+12]
  1054.     mov       bp,sp
  1055.     lds       si,[bp+12]         ; IV
  1056. ; Load and byte-swap IV
  1057.     mov       ax,[si]
  1058.     xchg        ah,al
  1059.     mov       x1,[si+2]
  1060.     mov       x2,[si+4]
  1061.     xchg        bh,bl
  1062.     xchg        ch,cl
  1063.     mov       dx,[si+6]
  1064.     xchg        dh,dl
  1065.  
  1066.     lds       si,[bp+16]         ; Key
  1067.     mov       x0,ax
  1068.     mov       x3,dx
  1069.  
  1070.     call        Core
  1071. IdeaCFBxLoop:
  1072. ;     mov        ax,x0
  1073. ;     mov        bp,sp
  1074. ;     dec        WORD PTR [bp+28]        ; Decrement count
  1075. ;     jz       IdeaCFBxEnd
  1076. ;     lds        si,[bp+20]
  1077. ;     les        di,[bp+24]
  1078. ;     mov        x0,ax
  1079. ; Alternate code: (which is faster?  Two moves or three segment overrides)
  1080.     mov       si,sp
  1081.     dec       WORD PTR ss:[si+28]
  1082.     jz      IdeaCFBxEnd
  1083.     les       di,ss:[si+24]
  1084.     lds       si,ss:[si+20]
  1085.  
  1086.     lodsw
  1087.     xchg        ah,al
  1088.     xchg        x0,ax
  1089.     xor       ax,x0
  1090.     xchg        ah,al
  1091.     stosw
  1092.     lodsw
  1093.     xchg        ah,al
  1094.     xchg        x1,ax
  1095.     xor       ax,x1
  1096.     xchg        ah,al
  1097.     stosw
  1098.     lodsw
  1099.     xchg        ah,al
  1100.     xchg        x2,ax
  1101.     xor       ax,x2
  1102.     xchg        ah,al
  1103.     stosw
  1104.     lodsw
  1105.     xchg        ah,al
  1106.     xchg        dx,ax
  1107.     xor       ax,dx
  1108.     xchg        ah,al
  1109.     stosw
  1110.  
  1111. ;     mov        ax,x0
  1112. ;     mov        bp,sp
  1113. ;     mov        [bp+20],si          ; Save source offset
  1114. ;     mov        [bp+24],di          ; Save destination offset
  1115. ;     lds        si,[bp+16]          ; Key
  1116. ;     mov        x0,ax         ; Get x0 in place for another iteration
  1117. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  1118.     mov       ax,si
  1119.     mov       si,sp
  1120.     mov       ss:[si+20],ax
  1121.     mov       ss:[si+24],di
  1122.     lds       si,ss:[si+16]
  1123.  
  1124.     mov       x3,dx        ; Get x3 in place
  1125.     mov       ax,OFFSET IdeaCFBxLoop
  1126.     push        ax
  1127.     jmp       Core
  1128.  
  1129. IdeaCFBxEnd:
  1130. ;     lds        si:[bp+12]
  1131.     lds       di,ss:[si+12]    ; Get IV for writing back
  1132.  
  1133.     mov       ax,x0
  1134.     xchg        ah,al
  1135.     mov       [di],ax          ; Use stosw?
  1136.     xchg        bh,bl
  1137.     xchg        ch,cl
  1138.     mov       [di+2],x1
  1139.     mov       [di+4],x2
  1140.     xchg        dh,dl
  1141.     mov       [di+6],dx
  1142.  
  1143.  
  1144.     pop       ds
  1145.     pop       di
  1146.     pop       si
  1147.     pop       bp
  1148.  
  1149.     ret
  1150.  
  1151.     endp
  1152. END_OF_FILE:
  1153. _TEXT ENDS
  1154. END START
  1155.