;-------------------------------------------------------------------------------- ; ; ; rel1.asm - ORB Open Random Bit Generator ; ; ; ; Copyright (C) 2000 A. Peter Allan ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program (gpl.txt); if not, write: ; ; ; ; Free Software Foundation, Inc. ; ; 59 Temple Place - Suite 330 ; ; Boston, MA 02111-1307 ; ; USA ; ; ; ; To contact the author write: ; ; ; ; A. Peter Allan ; ; APA Consulting ; ; 1323 Woodlawn Avenue ; ; Wilmington, DE 19806 ; ; alwynallan@yahoo.com ; ; ; ; Release 1 Freeze Date: July 27, 2000 ; ; ; ;-------------------------------------------------------------------------------- ; ; Compiles under Microchip Technology assembler MPASM v02.40 using the command ; ; MPASMWIN /e+ /l+ /x- /c+ /p12C671 rel1.asm ; ; The compiler is available at no charge from http://www.microchip.com ; ;-------------------------------------------------------------------------------- ; ;#define UDCN_OUT ; When defined (prefer setting assembler option) this ; option enables the use of pin 6 (GP1) as an ; input which outputs the User Defined Control Number ; whenever the pin is low. ; ;#define WINDOWED_PART ; When defined, the INTRC calibration value is compiled ; Comment out for production ; #define BITS_OUT_PER_ROUND D'64' ; Can be from D'1' to D'128' (whole hash) ; Reveal less hash for greater security ; #define INITIALIZATION_ROUNDS D'40' ; Can be from D'1' to D'255' to trade ; off entropy accumulation with start-up ; time. ; ; Memory Map: ; ----------------- ; H'2x' | Gen | Buf1 | H'Ax' ; ----------------- ; H'3x' | Gen | Buf2 | H'Bx' ; ----------------- ; H'4x' | Msg0 | XXXXX | H'Cx' ; ----------------- ; H'5x' | Msg1 | XXXXX | H'Dx' ; ----------------- ; H'6x' | Msg2 | XXXXX | H'Ex' ; ----------------- ; H'7x' | Buf0 | <-map | H'Fx' ; ----------------- ; Bank 0 Bank 1 ; ; Circuit: ; ; -------------- ; 2.5-5.5V --|1 8|-- 0V ; | | ; BAvail <-GP5--|2 7|--AN0------------ ; | | | ; Bit <-GP4--|3 6|--GP1 See Note | ; | | | ; BReq >-GP3--|4 5|--GP2--/\/\/\/--- ; -------------- 100K .1W 5% ; PIC12LC671-04I ; ; Note: Pin 6 (GP1) is configured as an output (low) in general use, and should ; be left unconnected. For use with UDCN_OUT defined, it is configured ; as an input (active low) and should be appropriately connected. ; #ifdef __12C671 PROCESSOR 12C671 ; PIC12C671 is the target processor #include "p12c671.inc"; include standard assembler stuff #else ERROR "Valid Processor type not defined." #endif ; #ifdef UDCN_OUT __CONFIG _MCLRE_OFF&_CP_ALL&_WDT_OFF&_INTRC_OSC_NOCLKOUT&_PWRTE_ON MESSG "UDCN_OUT defined" ; /\/\/\ Note: code protected with UDCN #else __CONFIG _MCLRE_OFF&_CP_OFF&_WDT_OFF&_INTRC_OSC_NOCLKOUT&_PWRTE_ON #endif ; bank_0 macro bcf STATUS,RP0 ; Bank0 ERRORLEVEL +302 ; turn on Bank 1 warning endm ; bank_1 macro bsf STATUS,RP0 ; Bank1 ERRORLEVEL -302 ; turn off Bank 1 warning endm ; CBLOCK H'20' TMP, I, J, K, L, M ; General use variables. Ctr0, Ctr1, Ctr2, Ctr3 ; Rounds counter for XOR'ing into entropy pool. ; At 64 bits/round, 1000 bits/second, counter ; will overflow in 8.71 years. ENDC ; Msg0 equ H'40' ; three 16 byte message blocks for MD2. The first Msg1 equ H'50' ; 31 bytes are the entropy pool Msg2 equ H'60' Buf0 equ H'70' ; three buffer blocks for MD2. The hash result is Buf1 equ H'A0' ; returned in Buf0 residual data is in Buf1-2. Buf2 equ H'B0' ; org H'0000' ; the reset vector call init ; initializes the chip call ld_uid ; load uid data in Msg0 and Msg1 to get started goto main ; ; could squeeze in one more op if space tight org H'0004' ; the interrupt vector retfie ; interrupts disabled, but here for safety anyway ; main call do_round ; do_round called 40 times for initialization movlw INITIALIZATION_ROUNDS subwf Ctr0,W btfss STATUS,Z goto main main2 movlw BITS_OUT_PER_ROUND movwf TMP ; set the number of bits to output movlw Buf0 movwf K ; set the source address of the bits call o_bits ; do the bit output call do_round ; do another round goto main2 ; and repeat ; ;-------------------------------------------------------------------------------- ; Routine do_round does all the non-IO things that happen for a round. ;-------------------------------------------------------------------------------- do_round call md2 ; do the MD2 hash call xor_uid ; xor unique id into residual call inc_ctr ; increment the rounds counter call recycle ; feed back hash, TMR0 and CTR0-3 to entropy pool call do_ads ; run A/D cycle into entopy pool return ; ;-------------------------------------------------------------------------------- ; Routine do_ads calls do_ad 261 times. First the stimulus sequence 1,0,1,0,1 ; is used to center the voltage on C_hold, then the 256 bits of the residual ; data, xor'ed with the uid (previously) and the last low bit of the A/D result ; (in this routine), are used. The low bit of the A/D result is xor'ed with the ; entropy pool for the last 248 calls. ;-------------------------------------------------------------------------------- do_ads bank_1 bsf TRISIO,2 ; GP2 is an input during this routine, except ; for 1us during each do_ad call bank_0 ; movlw HIGH mask_s movwf PCLATH ; set up PCLATH for mask_d call ; movlw D'5' ; five toggle cycles to center C_hold movwf I next_toggle movlw B'00000000' ; default GPIO btfsc I,0 movlw B'00000100' ; GPIO value with GP2 set movwf GPIO ; value set for do_ad call do_ad ; do the cycle decfsz I,F goto next_toggle ; ; note that I is always zero here -- no need to clear it as bit counter. next_bit clrf K ; K is used to determine the I'th stimulus bit movfw I ; get the bit counter andlw B'11111000' ; mask out the byte number *8 movwf FSR ; FSR contains byte number *8 bcf STATUS,C ; set up for rotate rrf FSR,F ; FSR contains byte number *4 rrf FSR,F ; FSR contains byte number *2 rrf FSR,F ; FSR contains byte number movlw Buf1 addwf FSR,F ; FSR points to the correct byte in residual movfw I ; get the bit counter andlw B'00000111' ; mask out the bit-in-byte call mask_d ; convert to mask value movwf J ; mask value stored in J, saves a mask_d call andwf INDF,W ; STATUS,Z now set if I'th residual bit is '0' ; btfss STATUS,Z ; if the bit is '1'... comf K,F ; ...flip the bits of K btfsc ADRES,0 ; if the last result bit is '1'... comf K,F ; ...flip the bits of K movfw K ; get K in W andlw B'00000100' ; screen out all except GP2 bit movwf GPIO ; put the value on the port call do_ad ; use GPIO value to do stimulus and get result ; movlw D'8' ; w contains 8 subwf I,W ; w contains 8-I btfss STATUS,C ; test for carry goto no_use ; first eight A/D results not used ; movlw Msg0-Buf1-1 addwf FSR,F ; FSR now points to target byte ; movfw J ; J contains the mask value btfsc ADRES,0 ; If the A/D low bit is set... xorwf INDF,F ; ...flip the appropriate bit of the entropy pool ; no_use incfsz I,F ; increment the bit counter goto next_bit ; repeat for 256 bits... ; clrf GPIO ; clear the outputs bank_1 bcf TRISIO,2 ; GP2 back to output to save power bank_0 return ; ;-------------------------------------------------------------------------------- ; Routine do_ad stimulates C_hold with bit GPIO,2 and returns with A/D result ; in ADRES. Uses W. ;-------------------------------------------------------------------------------- do_ad movlw B'01000001' ; A/D clock is Fosc/8, A/D module on movwf ADCON0 ; do it, starts sampling ; bank_1 bcf TRISIO,2 ; GP2 to low-impedance to charge/discharge Chold bsf TRISIO,2 ; GP2 back to high impedance bank_0 ; bsf ADCON0,GO ; starts conversion, ends sampling? wait_for_ad btfsc ADCON0,GO ; test GO bit goto wait_for_ad clrf ADCON0 ; turn A/D off ; return ; ;-------------------------------------------------------------------------------- ; Routine o_bits does data output to host. Call with Number of bits to output ; in TMP, and address of source bits in K. Uses I, L, FSR, PCLATH. ;-------------------------------------------------------------------------------- o_bits clrf I ; I is the bit to output movlw HIGH mask_s movwf PCLATH ; set up PCLATH for mask_d call b_avail movlw B'00100000' ; to avoid the instruction: bsf GPIO,5 (See ; manual on read-modify-write instructions) movwf GPIO ; Raise BAvail to signal that bit is available clrf L ; Loop counter wait_hi btfsc GPIO,3 ; Skip if BReq is low goto set_up ; The user wants it decfsz L,F ; decrement the loop counter goto wait_hi ; Wait for user if < 256 loops (about 1.2ms) ; This introduces some entropy in TMR0 and ; speeds the data output bcf INTCON,GPIF ; clear the flag so it will sleep slp_hi sleep ; sleep until one of GP0, GP1, or GP3 changes goto wait_hi ; Go and see if it was GP3 (BReq) set_up #ifdef UDCN_OUT btfss GPIO,1 ; Is Pin 6 dropped? call o_udcn ; yes: output UDCN #endif ;UDCN_OUT movfw I get_bit andlw B'11111000' ; screen out the byte number movwf FSR ; byte number * 8 in FSR bcf STATUS,C ; clear the carry bit rrf FSR,F ; byte number * 4 in FSR rrf FSR,F ; byte number * 2 in FSR rrf FSR,F ; byte number in FSR movfw K ; bit array base addwf FSR,F ; FSR points to byte movfw I andlw B'00000111' ; screen out the bit number call mask_d ; get the bit mask scr_bit andwf INDF,W ; screen the bit... STATUS,Z set if bit is '0' movlw B'00000000' ; one option btfss STATUS,Z ; Skip if bit is zero movlw B'00010000' ; overwrite W to set Bit output ; note: timing is the same for 0 and 1 preventing ; any timing based attack. see_bit movwf GPIO ; set the output wait_lo btfsc GPIO,3 ; Skip if BReq has gone low goto wait_lo drop_it ; the user has seen it, so clrf GPIO ; drop Bit so that others don't see it incf I,F movfw TMP ; TMP contains the bit count for the o_bits call subwf I,W btfss STATUS,Z goto b_avail return ; ;-------------------------------------------------------------------------------- ; Routine inc_ctr increments the 32 bit rounds counter. It uses a fixed number ; of processor cycles regardless of overflow to prevent timing attack. ;-------------------------------------------------------------------------------- inc_ctr incf Ctr0,F btfsc STATUS,Z incf Ctr1,F btfsc STATUS,Z incf Ctr2,F btfsc STATUS,Z incf Ctr3,F return ; ;-------------------------------------------------------------------------------- ; Routine md2 does the MD2 hash on the message in Msg0 and Msg1 ; ; Notes: The message must be padded with at least one byte to fill ; Msg0 and Msg1. The pad value is the number of bytes padded. ; See RFC1319 and revision in RFC1423 for MD2 specification. ; Only the first block of the buffer is cleared, as it is ; believed that this does not affect the result. ; MD2 may be intellectual property of RSA Data Security Inc. ; A license for commercial use has not been obtained from RSA. ; ; Memory: Uses TMP, I, J, L, Msg2, Buf0, Buf1, Buf2. Code must be changed ; for address calculation if any of Buf0-2 are moved. ; ; Result: 128-bit Message Digest (hash) is in Buf0. Buf1 and Buf2 are ; left in their final state, called the residual data. ;-------------------------------------------------------------------------------- md2 movlw Msg2 ; clear the checksum in Msg2 movwf FSR nextc clrf INDF incf FSR,F btfss FSR,4 ; cheap compare - adjust if Msg2 moves goto nextc ; checksum is cleared ; clrf L ; now, calculate the checksum ; movlw HIGH pi_s movwf PCLATH ; set data table page clrf I ; I is B'iiiijjjj' per RFC1319 nextI movfw I ; W is I addlw Msg0 ; W points to M[i*16+j] movwf FSR ; FSR points to M[i*16+j] movfw INDF ; W is c=M[i*16+j], c not stored xorwf L,W ; W is c xor L movwf TMP ; TMP is c xor L movfw I andlw B'00001111' ; W is j addlw Msg2 ; W points to C[j] movwf FSR ; FSR points to C[j] movfw TMP ; w is c xor L call pi_d ; w is S[c xor L] xorwf INDF,F ; C[j] is C[j] xor S[c xor L], per RFC1423 movfw INDF ; w is C[j] movwf L ; L is C[j] incf I,F btfss I,5 ; cheap compare goto nextI ; repeat for all 32 bytes in Msg0 & Msg1 ; ; Process the 48 byte checksum appended message ; clrbuf movlw Buf0 ; clear Buf0 movwf FSR nextd clrf INDF incf FSR,F btfss FSR,7 ; cheap compare, change ifBuf0 moves goto nextd ; Buf0 is cleared ; Buf1 & Buf2 are OK, despite RFC1319 ; iloop clrf I ; PCLATH is still set for pi_s forI clrf J forJ movfw I movwf TMP swapf TMP,W ; W is i*16 addwf J,W ; W is i*16+j addlw Msg0 ; W points to M[i*16+j] movwf FSR ; FSR points to M[i*16+j] movfw INDF ; W is M[i*16+j] movwf TMP ; TMP is M[i*16+j] movfw J ; W is J addlw Buf1 ; W points to X[16+j] movwf FSR ; FSR points to X[16+j] movfw TMP ; W is M[i*16+j] movwf INDF ; X[16+j] <- M[i*16+j] movwf TMP ; TMP is X[16+j] movfw J ; W is j addlw Buf0 ; W points to X[j] movwf FSR ; FSR points to X[j] movfw INDF ; W is X[j] xorwf TMP,F ; TMP is (X[16+j] xor X[j]) movfw J ; W is j addlw Buf2 ; W points to X[j+32] movwf FSR ; FSR points to X[j+32] movfw TMP ; W is (X[16+j] xor X[j]) movwf INDF ; X[j+32] <- (X[j+16] xor X[j]) ; incf J,F btfss J,4 ; cheap compare goto forJ ; do while j<16 ; ; Note: most of the code for this application is written for easy readability, ; sometimes at the expense of speed. The following loops are optimized ; for speed, and their function may be obscured. This is because these ; loops consume the bulk of the processor cycles, and therefore limit ; the bits per second generated. ; clrf L ; t<-0 (L is used for RFC1319's t) clrf J forJJ movlw Buf0 movwf FSR ; FSR points to X[k] ; movfw L ; W is t forK0 call pi_d ; W is S[t] xorwf INDF,W ; W is (X[k] xor S[t]) movwf INDF ; X[k] <- (X[k] xor S[t]) incf FSR,F btfss FSR,7 goto forK0 bsf FSR,5 ; Switches H'80' to H'A0' forK1 call pi_d ; W is S[t] xorwf INDF,W ; W is (X[k] xor S[t]) movwf INDF ; X[k] <- (X[k] xor S[t]) incf FSR,F btfss FSR,6 goto forK1 movwf L ; t <- X[k] ; movfw J addwf L,F ; t <- (t+j) mod 256 ; incf J,F movfw J sublw D'18' btfss STATUS,Z goto forJJ ; do while j<18 ; incf I,F movfw I sublw D'3' btfss STATUS,Z goto forI ; do while i<3 (for each message block) ; return ; all done ; ;-------------------------------------------------------------------------------- ; Routine init initializes special registers on the processor chip ;-------------------------------------------------------------------------------- init clrf TMR0 clrf GPIO ; Do it while we are in Bank 0 bank_1 ; macro switches to Bank 1 bcf OPTION_REG,T0CS ; TMR0 clock source is Internal Instruction ; Cycle Clock. call H'03ff' ; Get osc calibration value movwf OSCCAL ; Set the oscillator calibration. movlw B'00000110' ; GP0 is analog only movwf ADCON1 #ifdef UDCN_OUT movlw B'00001011' ; GP3 and GP1 and AN0 are inputs #else movlw B'00001001' ; GP3 and AN0 are inputs #endif ;UDCN_OUT movwf TRISIO ; Set the tri-state buffers bank_0 ; Back to Bank 0 ; movlw B'00001000' movwf INTCON ; Global interrupt disable, and enable GPIO ; Interrupt on Change. This will enable a wake ; from sleep when GP3 is raised. clrf Ctr0 ; Clear the rounds counter clrf Ctr1 clrf Ctr2 clrf Ctr3 return ; ;-------------------------------------------------------------------------------- ; Recycle hash in Buf0 by xor'ing into Msg0. Also xor's TMR0 and Ctr into Msg1 ; Uses I,TMP,FSR. ;-------------------------------------------------------------------------------- recycle clrf I ; clear the byte counter recI movfw I ; W contains the byte counter addlw Buf0 ; W contains the hash byte address movwf FSR ; FSR points to the hash byte movfw INDF ; W contains the hash byte movwf TMP ; TMP contains the hash byte movfw I ; W contains the byte counter addlw Msg0 ; W contains the entropy pool byte address movwf FSR ; FSR points to the entropy pool byte movfw TMP ; W contains the hash byte xorwf INDF,F ; hash byte is xor'ed into the entropy pool incf I,F ; increment byte counter btfss I,4 goto recI ; do while i<16 (for whole hash block) ; movfw TMR0 ; xor TMR0 into next 7 bytes xorwf Msg1+H'00',F xorwf Msg1+H'01',F xorwf Msg1+H'02',F xorwf Msg1+H'03',F xorwf Msg1+H'04',F xorwf Msg1+H'05',F xorwf Msg1+H'06',F ; movfw Ctr3 ; xor Ctr0-3 (twice) into next 8 bytes xorwf Msg1+H'07',F xorwf Msg1+H'0B',F movfw Ctr2 xorwf Msg1+H'08',F xorwf Msg1+H'0C',F movfw Ctr1 xorwf Msg1+H'09',F xorwf Msg1+H'0D',F movfw Ctr0 xorwf Msg1+H'0A',F xorwf Msg1+H'0E',F ; movlw H'01' movwf Msg1+H'0F' ; add the padding (should already be there) ; return ; all done ; ;-------------------------------------------------------------------------------- ; Routine xor_uid xor's the 32 byte unique id into the hash residual in Buf1 and ; Buf2. Uses FSR, TMP, W, and PCLATH. ;-------------------------------------------------------------------------------- xor_uid movlw Buf1 ; set the destination movwf FSR clrf TMP ; clear the counter movlw HIGH unique_id_s ; set uid page movwf PCLATH moreuid movfw TMP call unique_id ; get the byte xorwf INDF,F ; xor it into the residual incf FSR,F incf TMP,F btfss TMP,5 ; test for 32 bytes done goto moreuid return ; ;-------------------------------------------------------------------------------- ; Routine ld_uid loads the first 31 bytes of the unique id table into Msg0 ; and Msg1 and pads the message with D'1' ;-------------------------------------------------------------------------------- ld_uid movlw Msg0 ; set the destination movwf FSR clrf TMP ; clear the counter movlw HIGH unique_id_s ; set pi table page movwf PCLATH moreldu movfw TMP call unique_id ; get the byte movwf INDF ; put it in the table incf FSR,F incf TMP,F btfss TMP,5 ; test for 32 bytes done goto moreldu movlw D'1' movwf Msg1+H'0F' return ; ;-------------------------------------------------------------------------------- ; Routine o_udcn does UDCN output to host. Continues (loops through data) as long ; as Pin 6 (GP1) is held low. Uses L, M. ;-------------------------------------------------------------------------------- #ifdef UDCN_OUT ; only gets here if host has dropped GP1. ; only gets out when GP1 raised. o_udcn movlw D'128' ; 128 bits of UDCN movwf L ; L is the bit to output ; PCLATH assumed set for mask_d call ; bit available: ba_udcn movlw B'00100000' ; to avoid the instruction: bsf GPIO,5 (See ; manual on read-modify-write instructions) movwf GPIO ; Raise BAvail to signal that bit is available ; this should cause no problem on the first ; loop through wh_udcn btfss GPIO,3 ; Skip if BReq is high goto wh_udcn ; Wait for user ; No sleeping here! su_udcn decf L,W ; set_up andlw B'11111000' ; get_bit: screen out the byte number movwf M ; byte number * 8 in M bcf STATUS,C ; clear the carry bit rrf M,F ; byte number * 4 in M rrf M,F ; byte number * 2 in M rrf M,F ; byte number in M movfw M call udcn_d movwf M decf L,W andlw B'00000111' ; screen out the bit number call mask_d ; get the bit mask andwf M,W ; screen the bit... STATUS,Z set if bit is '0' movlw B'00000000' ; one option btfss STATUS,Z ; Skip if bit is zero movlw B'00010000' ; overwrite W to set Bit output ; note: timing is the same for 0 and 1 preventing ; any timing based attack. movwf GPIO ; set the output wl_udcn btfsc GPIO,3 ; Skip if BReq has gone low goto wl_udcn ; the user has seen it, so clrf GPIO ; drop Bit so that others don't see it btfsc GPIO,1 return decfsz L,F goto ba_udcn goto o_udcn #endif ;UDCN_OUT ; ;-------------------------------------------------------------------------------- ; org H'01ff' ; Data space. Since pi_d table has 256 values ; we must start the routine one prior to a page ; boundary to avoid complication with PCLATH. ; ;-------------------------------------------------------------------------------- ; Routine (data table) pi_d returns in W the S[W] lookup value. S[] is a ; permutation of the 256 byte values based on the digits of Pi. Data is taken ; from RFC1319 and may be copyrighted intellectual property of RSA Data ; Security, Inc. A license for commercial use has not been obtained from RSA. ;-------------------------------------------------------------------------------- pi_d addwf PCL,F ; PCLATH must be set to HIGH pi_s before calling. pi_s retlw D'41' retlw D'46' retlw D'67' retlw D'201' retlw D'162' retlw D'216' retlw D'124' retlw D'1' retlw D'61' retlw D'54' retlw D'84' retlw D'161' retlw D'236' retlw D'240' retlw D'6' retlw D'19' retlw D'98' retlw D'167' retlw D'5' retlw D'243' retlw D'192' retlw D'199' retlw D'115' retlw D'140' retlw D'152' retlw D'147' retlw D'43' retlw D'217' retlw D'188' retlw D'76' retlw D'130' retlw D'202' retlw D'30' retlw D'155' retlw D'87' retlw D'60' retlw D'253' retlw D'212' retlw D'224' retlw D'22' retlw D'103' retlw D'66' retlw D'111' retlw D'24' retlw D'138' retlw D'23' retlw D'229' retlw D'18' retlw D'190' retlw D'78' retlw D'196' retlw D'214' retlw D'218' retlw D'158' retlw D'222' retlw D'73' retlw D'160' retlw D'251' retlw D'245' retlw D'142' retlw D'187' retlw D'47' retlw D'238' retlw D'122' retlw D'169' retlw D'104' retlw D'121' retlw D'145' retlw D'21' retlw D'178' retlw D'7' retlw D'63' retlw D'148' retlw D'194' retlw D'16' retlw D'137' retlw D'11' retlw D'34' retlw D'95' retlw D'33' retlw D'128' retlw D'127' retlw D'93' retlw D'154' retlw D'90' retlw D'144' retlw D'50' retlw D'39' retlw D'53' retlw D'62' retlw D'204' retlw D'231' retlw D'191' retlw D'247' retlw D'151' retlw D'3' retlw D'255' retlw D'25' retlw D'48' retlw D'179' retlw D'72' retlw D'165' retlw D'181' retlw D'209' retlw D'215' retlw D'94' retlw D'146' retlw D'42' retlw D'172' retlw D'86' retlw D'170' retlw D'198' retlw D'79' retlw D'184' retlw D'56' retlw D'210' retlw D'150' retlw D'164' retlw D'125' retlw D'182' retlw D'118' retlw D'252' retlw D'107' retlw D'226' retlw D'156' retlw D'116' retlw D'4' retlw D'241' retlw D'69' retlw D'157' retlw D'112' retlw D'89' retlw D'100' retlw D'113' retlw D'135' retlw D'32' retlw D'134' retlw D'91' retlw D'207' retlw D'101' retlw D'230' retlw D'45' retlw D'168' retlw D'2' retlw D'27' retlw D'96' retlw D'37' retlw D'173' retlw D'174' retlw D'176' retlw D'185' retlw D'246' retlw D'28' retlw D'70' retlw D'97' retlw D'105' retlw D'52' retlw D'64' retlw D'126' retlw D'15' retlw D'85' retlw D'71' retlw D'163' retlw D'35' retlw D'221' retlw D'81' retlw D'175' retlw D'58' retlw D'195' retlw D'92' retlw D'249' retlw D'206' retlw D'186' retlw D'197' retlw D'234' retlw D'38' retlw D'44' retlw D'83' retlw D'13' retlw D'110' retlw D'133' retlw D'40' retlw D'132' retlw D'9' retlw D'211' retlw D'223' retlw D'205' retlw D'244' retlw D'65' retlw D'129' retlw D'77' retlw D'82' retlw D'106' retlw D'220' retlw D'55' retlw D'200' retlw D'108' retlw D'193' retlw D'171' retlw D'250' retlw D'36' retlw D'225' retlw D'123' retlw D'8' retlw D'12' retlw D'189' retlw D'177' retlw D'74' retlw D'120' retlw D'136' retlw D'149' retlw D'139' retlw D'227' retlw D'99' retlw D'232' retlw D'109' retlw D'233' retlw D'203' retlw D'213' retlw D'254' retlw D'59' retlw D'0' retlw D'29' retlw D'57' retlw D'242' retlw D'239' retlw D'183' retlw D'14' retlw D'102' retlw D'88' retlw D'208' retlw D'228' retlw D'166' retlw D'119' retlw D'114' retlw D'248' retlw D'235' retlw D'117' retlw D'75' retlw D'10' retlw D'49' retlw D'68' retlw D'80' retlw D'180' retlw D'143' retlw D'237' retlw D'31' retlw D'26' retlw D'219' retlw D'153' retlw D'141' retlw D'51' retlw D'159' retlw D'17' retlw D'131' retlw D'20' ; ;-------------------------------------------------------------------------------- ; Routine (data table) unique_id returns the UID byte called for by 0 <= W <= 31. ; The second 16 bytes are the complements of the first 16 to prevent over-write ; modification. With Release 0 (Non-GPL) each chip had a unique number here. For ; this release the Unique ID is fixed, and was obtained from the command ; ; > md5sum gpl.txt ; 0636e73ff0215e8d672dc4c32c317bb3 *gpl.txt ; ; The data is used to initialize the entropy pool, and to salt the residual data ; after each hash. ;-------------------------------------------------------------------------------- unique_id addwf PCL,F unique_id_s retlw H'06' ; 16 byte unique id satrts here retlw H'36' retlw H'e7' retlw H'3f' retlw H'f0' retlw H'21' retlw H'5e' retlw H'8d' retlw H'67' retlw H'2d' retlw H'c4' retlw H'c3' retlw H'2c' retlw H'31' retlw H'7b' retlw H'b3' ; retlw ~H'06' ; next 16 bytes are the complements of the first 16. retlw ~H'36' retlw ~H'e7' retlw ~H'3f' retlw ~H'f0' retlw ~H'21' retlw ~H'5e' retlw ~H'8d' retlw ~H'67' retlw ~H'2d' retlw ~H'c4' retlw ~H'c3' retlw ~H'2c' retlw ~H'31' retlw ~H'7b' retlw ~H'b3' ; ;-------------------------------------------------------------------------------- ; Routine (data table) mask_d returns the byte mask to screen the bit indicated ; by 0 <= W <= 7. ;-------------------------------------------------------------------------------- mask_d addwf PCL,F mask_s retlw B'00000001' retlw B'00000010' retlw B'00000100' retlw B'00001000' retlw B'00010000' retlw B'00100000' retlw B'01000000' retlw B'10000000' ; ;-------------------------------------------------------------------------------- ; The User Defined Control Number (UDCN) included for UDCN_OUT ;-------------------------------------------------------------------------------- #ifdef UDCN_OUT udcn_d addwf PCL,F udcn_s retlw H'AA' ; A's are the serial number retlw H'AA' retlw H'AA' retlw H'AA' retlw H'BB' ; B's are the revision number retlw H'BB' retlw H'CC' ; C's are the Burn Date retlw H'CC' retlw H'CC' retlw H'CC' retlw H'00' retlw H'00' retlw H'00' retlw H'00' retlw H'00' retlw H'00' #endif ; ;-------------------------------------------------------------------------------- ; Copyright notice, burned to chip ;-------------------------------------------------------------------------------- DT " Copyright (C) 2000 A. Peter Allan " ; ;-------------------------------------------------------------------------------- ; Note: There's more space up here for code! ;-------------------------------------------------------------------------------- ; #ifdef WINDOWED_PART org H'03ff' retlw H'B4' ; The INTRC calibration value #endif ; END