home *** CD-ROM | disk | FTP | other *** search
/ PCMania 10 / Pcmania_Ep2_10_CD-01.iso / ARTICULOS / tecnologia / SECD13C.ZIP / SECTSR.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-03-28  |  24.7 KB  |  1,192 lines

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