ganavel9783
Member level 1
Hi people,
I recently posted a thread about data truncation problem with text file encryption. I overcame the problem by placing a delay function(sleep) in my pc application.
However when i tried to encrypt a plain text file, i notice that sometimes there are missing bytes(1,2,3 or more sometimes) for the encrypted text.So surely the decrypted text is not going to be same as the original text. Here is an example of the text files for the encryption and also decryption.
My pc application sends the 16 byte key followed by a special a non-printable ascii character to distinguish key data and the next 16 byte data (original text or encrypted text) is send followed by a special character. Here is an example:
This will continue until all the 16 byte blocks of the plain text file is fully encrypted.
To get the the original text, decryption is done.my pc application send the encrypted text by this manner:
This will continue until all the 16 byte blocks of the encrypted text file is fully decrypted.
For ur information i'm using the AES algorithm which i've implemented into PIC16f877 using UART full duplex mode.
As u can c, the encrypted text is suppose to be 112 bytes. Since the last 16 byte block for the plain text is incomplete, it is padded with space characters to make it into a full block of 16 bytes.
I do realise that encrypting and decrypting a 16 byte block data does take time(about 1.0546 ms for encryption and 1.4682 ms for decryption). Thats the reason i place a delay in my GUI so that i send the next 16 byte block data once the previous 16 byte block data is either encrypted or decrypted and send back to PC.I tried reviewing my .asm code for PIC16f877 chip that i'm using and i also looked into the bauda rates and the ext oscillator but i'm still having this missing byte problem. Its also strange that it works sometimes with different keys.
So my questions are:
1) y is there missing bytes even though i've placed a delay in my GUI?
2) How many bytes can serial port support to transfer large text files?
3) Is there any solution to my problems?
The .asm file that i've used for my chip shown below. U can run through the code in MPLAB n c it for urself.Its kinda long:-(.
Regards,
ganavel9783
I recently posted a thread about data truncation problem with text file encryption. I overcame the problem by placing a delay function(sleep) in my pc application.
However when i tried to encrypt a plain text file, i notice that sometimes there are missing bytes(1,2,3 or more sometimes) for the encrypted text.So surely the decrypted text is not going to be same as the original text. Here is an example of the text files for the encryption and also decryption.
key used for both encryption & decryption:waltwhitman,poet
plain text (106 bytes):
I pass death with the dying and birth with new washed baby, and am not contained between my hat and boots.
encrypted text (111 bytes):
·ç~Pɲ¼”äriÁ7÷è‰wíÿK=:r5oéÎKFÂ6’ßú†Í-!ºDfbÆü{ßÓiGÃ|ÓœëxÎåEسՙ¿U™™iªÁú d‚0ã~åà bü²à‘úCä̆ës¯÷K
ä
decrypted text(111 bytes):
I pass death with the dying and birth with nè8Ýà»P—ML!¥þ€|±^àTNä±¼WSÙÇ»öXÞŸ…iˆ{æã¯uœ?c‰ÙjF¨ÍSˆ„§8ÚÜPIÕn
My pc application sends the 16 byte key followed by a special a non-printable ascii character to distinguish key data and the next 16 byte data (original text or encrypted text) is send followed by a special character. Here is an example:
<16 byte key><1 byte BEL character><16 byte original text><1 byte carriage return character>[delay for 5 ms]<16 byte original text><1 byte carriage return character>[delay for 5 ms]<16 byte original text><1 byte carriage return character>[delay for 5 ms]
This will continue until all the 16 byte blocks of the plain text file is fully encrypted.
To get the the original text, decryption is done.my pc application send the encrypted text by this manner:
<16 byte key><1 byte BEL character><16 byte encrypted text><1 byte line feed character>[delay for 6 ms]<16 byte encrypted text><1 byte line feed character>[delay for 6 ms]<16 byte encrypted text><1 byte line feed character>[delay for 6 ms]
This will continue until all the 16 byte blocks of the encrypted text file is fully decrypted.
For ur information i'm using the AES algorithm which i've implemented into PIC16f877 using UART full duplex mode.
As u can c, the encrypted text is suppose to be 112 bytes. Since the last 16 byte block for the plain text is incomplete, it is padded with space characters to make it into a full block of 16 bytes.
I do realise that encrypting and decrypting a 16 byte block data does take time(about 1.0546 ms for encryption and 1.4682 ms for decryption). Thats the reason i place a delay in my GUI so that i send the next 16 byte block data once the previous 16 byte block data is either encrypted or decrypted and send back to PC.I tried reviewing my .asm code for PIC16f877 chip that i'm using and i also looked into the bauda rates and the ext oscillator but i'm still having this missing byte problem. Its also strange that it works sometimes with different keys.
So my questions are:
1) y is there missing bytes even though i've placed a delay in my GUI?
2) How many bytes can serial port support to transfer large text files?
3) Is there any solution to my problems?
The .asm file that i've used for my chip shown below. U can run through the code in MPLAB n c it for urself.Its kinda long:-(.
Regards,
ganavel9783
Code:
;=============================================================================
; Filename: AES.asm
;=============================================================================
; Author: ganavel9783
; Company: Home
; Revision: 1.00
; Date: 28th February, 2006
; Last Revised: 29th March,2006
; Assembled using MPLAB V7.20(QuickBuild Option)
;=============================================================================
; Include Files: p16f877.inc V1.12
;=============================================================================
; This code uses USART implementation with transmit and receive
; interrupts.Received data is put into a buffer, called RxBuffer. When a
; non printable ASCII character(<CR> for encrypt or <LF> for decrypt)is
; received,the received data in RxBuffer is either encrypted or
; decrypted using the Advanced Encryption Standard(AES) algorithm before
; being moved into another buffer,called TxBuffer. The data in TxBuffer
; is then transmitted.Besides that, there are 2 types of key buffer
; (constant and overwritten). Constant key buffer is called KeyBuffer
; while another key buffer that is overwritten during the period of
; encryption is called key. This key data is distinguished by detecting
; a <BEL> character.This code is a combination of codes from
; Microchip's P16_tiri.asm(Application Note 774) and aes_rijn.asm
; (Application Note 821).
;=============================================================================
list p=16f877 ;list directive to define processor
#include <p16f877.inc> ;processor specific definitions
errorlevel -302 ;suppress "not in bank 0" message
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_OFF & _LVP_OFF & _DEBUG_OFF & _CPD_OFF
;----------------------------------------------------------------------------
;Constants
SPBRG_VAL EQU .65 ;set baud rate 19200 for 20.228Mhz clock
TX_BUF_LEN EQU .16 ;length of transmit circular buffer
RX_BUF_LEN EQU TX_BUF_LEN ;length of receive circular buffer
KEY_BUF_LEN EQU TX_BUF_LEN ;user input key buffer
ROUNDS equ 0x0A ;number of rounds necessary to cipher/decipher
INIT_RAM0 equ 0x20 ;Starting point of RAM in segment 0
INIT_RAM1 equ 0xA0 ;Starting point of RAM in segment 1
INIT_RAM2 equ 0x30 ;Starting point of RAM in segment 2
;----------------------------------------------------------------------------
;Bit Definitions for Flags Register
TxBufFull EQU 0 ;bit indicates Tx buffer is full
TxBufEmpty EQU 1 ;bit indicates Tx buffer is empty
RxBufFull EQU 2 ;bit indicates Rx buffer is full
RxBufEmpty EQU 3 ;bit indicates Rx buffer is empty
ReceivedCR EQU 4 ;bit indicates <CR> character received(Encrypt)
ReceivedLF EQU 5 ;bit indicates <LF> character recieved(Decrypt)
;----------------------------------------------------------------------------
;Bit Definitions for Flags2 Register
KeyBufFull EQU 0 ;bit indicates Key buffer is full
KeyBufEmpty EQU 1 ;bit indicates Key buffer is empty
ReceivedBEL EQU 2 ;bit indicates <BEL> character received(Key Set Up)
;----------------------------------------------------------------------------
;Variables
CBLOCK 0x70
WREG_TEMP ;storage for WREG during interrupt
STATUS_TEMP ;storage for STATUS during interrupt
PCLATH_TEMP ;storage for PCLATH during interrupt
FSR_TEMP ;storage for FSR during interrupt
ENDC
CBLOCK 0x20
Flags ;byte to store indicator flags
Flags2 ;byte to store indicator flags for key
TempData ;temporary data in main routines
BufferData ;temporary data in buffer routines
TxStartPtr ;pointer to start of data in TX buffer
TxEndPtr ;pointer to end of data in TX buffer
RxStartPtr ;pointer to start of data in RX buffer
RxEndPtr ;pointer to end of data in RX buffer
KeyStartPtr ;pointer to start of data in Key2 buffer
KeyEndPtr ;pointer to end of data in Key2 buffer
TestFlagsReg ;Flags & Flags2 register indicator for
ENDC ;cipher text data(decrypt)
CBLOCK 0x140
aux ;general purpose variables
aux1
aux2
aux3
ENDC
CBLOCK 0x144
round_counter ;encryption/decryption rounds counter
rcon
ENDC
CBLOCK 0x14A
d0
d1
d2
ENDC
CBLOCK 0xA0
TxBuffer:TX_BUF_LEN ;transmit data buffer
ENDC
CBLOCK 0x150
RxBuffer:RX_BUF_LEN ;receive data buffer
ENDC
block equ RxBuffer ;block vector (16 bytes*8=>128 bits)
CBLOCK 0x130
KeyBuffer:KEY_BUF_LEN ;constant key from user input
ENDC
CBLOCK 0x160
key:KEY_BUF_LEN ;key vector (16 bytes*8=>128 bits)
ENDC ;overwritten during ecryption & decryption
;-----------------------------------------------------------------------------
;Macros to select the register bank
;Many bank changes can be optimized when only one STATUS bit changes
Bank0 MACRO ;macro to select data RAM bank 0
bcf STATUS,IRP
bcf STATUS,RP0
bcf STATUS,RP1
ENDM
Bank1 MACRO ;macro to select data RAM bank 1
bcf STATUS,IRP
bsf STATUS,RP0
bcf STATUS,RP1
ENDM
Bank2 MACRO ;macro to select data RAM bank 2
bsf STATUS,IRP
bcf STATUS,RP0
bsf STATUS,RP1
ENDM
Bank3 MACRO ;macro to select data RAM bank 3
bsf STATUS,IRP
bsf STATUS,RP0
bsf STATUS,RP1
ENDM
;----------------------------------------------------------------------------
;This code executes when a reset occurs.
ORG 0x0000 ;place code at reset vector
ResetCode: clrf PCLATH ;select program memory page 0
goto Main ;go to beginning of program
;----------------------------------------------------------------------------
;This code executes when an interrupt occurs.
ORG 0x0004 ;place code at interrupt vector
InterruptCode: movwf WREG_TEMP ;save WREG
movf STATUS,W ;store STATUS in WREG
clrf STATUS ;select file register bank0
movwf STATUS_TEMP ;save STATUS value
movf PCLATH,W ;store PCLATH in WREG
movwf PCLATH_TEMP ;save PCLATH value
clrf PCLATH ;select program memory page0
movf FSR,W ;store FSR in WREG
movwf FSR_TEMP ;save FSR value
;test other interrupt flags here
Bank0 ;select bank0
btfsc PIR1,RCIF ;test RCIF receive interrupt
bsf STATUS,RP0 ;change to bank1 if RCIF set
btfsc PIE1,RCIE ;test if interrupt enabled if RCIF set
goto GetData ;if RCIF and RCIE set, do receive
Bank0 ;select bank0
btfsc PIR1,TXIF ;test for TXIF transmit interrupt
bsf STATUS,RP0 ;change to bank1 if TXIF set
btfsc PIE1,TXIE ;test if interrupt enabled if TXIF set
goto PutData ;if TXIF and TCIE set, do transmit
;can do special error handling here - an unexpected interrupt occurred
goto EndInt
;------------------------------------
;Get received data and write into receive buffer.
GetData: Bank0
btfsc RCSTA,OERR ;test overrun error flag
goto ErrOERR ;handle it if error
btfsc RCSTA,FERR ;test framing error flag
goto ErrFERR ;handle it if error
btfsc Flags,RxBufFull ;check if buffer full
goto ErrRxOver ;handle it if full
movf RCREG,W ;get received data
call PutRxBuffer ;and put in buffer
goto EndInt
;error because OERR overrun error bit is set
;can do special error handling here - this code simply clears and continues
ErrOERR: bcf RCSTA,CREN ;reset the receiver logic
bsf RCSTA,CREN ;enable reception again
goto EndInt
;error because FERR framing error bit is set
;can do special error handling here - this code simply clears and continues
ErrFERR: movf RCREG,W
goto EndInt
;error because receive buffer is full and new data has been received
;can do special error handling here - this code simply receives data
;and test to distiguish type of data and later discards the data
;and continues
ErrRxOver: clrf TestFlagsReg
movf RCREG,W ;discard received data that has error
movwf TestFlagsReg ;place received data to TestFlags2Reg
movf TestFlagsReg,W ;distinguish type of data received
xorlw 0x07 ;compare with <BEL>
btfsc STATUS,Z ;check if the same
bsf Flags2,ReceivedBEL;indicate <BEL> character received
xorlw 0x07 ;change back to valid data
xorlw 0x0d ;compare with <CR>
btfsc STATUS,Z ;check if the same
bsf Flags,ReceivedCR;indicate <CR> character received
xorlw 0x0d ;change back to valid data
xorlw 0x0a ;compare with <LF>
btfsc STATUS,Z ;check if the same
bsf Flags,ReceivedLF;indicate <LF> character received
goto EndInt
;------------------------------------
;Read data from the transmit buffer and transmit the data.
PutData: Bank0 ;select bank 0
btfss Flags,TxBufEmpty ;check if transmit buffer empty
goto PutDat1 ;if not then go get data and transmit
Bank1 ;select bank1
bcf PIE1,TXIE ;disable TX interrupt because all done
goto EndInt
PutDat1: call GetTxBuffer ;get data to transmit
movwf TXREG ;and transmit
;------------------------------------
;End of interrupt routine restores context
EndInt: Bank0 ;select bank 0
movf FSR_TEMP,W ;get saved FSR value
movwf FSR ;restore FSR
movf PCLATH_TEMP,W ;get saved PCLATH value
movwf PCLATH ;restore PCLATH
movf STATUS_TEMP,W ;get saved STATUS value
movwf STATUS ;restore STATUS
swapf WREG_TEMP,F ;prepare WREG to be restored
swapf WREG_TEMP,W ;restore WREG without affecting STATUS
retfie ;return from interrupt
;----------------------------------------------------------------------------
;Main routine to clear ram locations,check for reception of <CR>,<LF> and <BEL>
;to distinguish plaintext data,ciphertext data and key data and calls a routine
;to move the data to transmit back.
Main: call init_cpu0 ;start CPU registers
call init_cpu1
call init_cpu2
call SetupSerial ;set up serial port and buffers
goto MainLoop
init_cpu0: Bank0 ;clear RAM(0x0020-0x007f)in bank0
movlw INIT_RAM0 ;points to the start of RAM0
movwf FSR
CleanB0: clrf INDF ;clear RAM location pointed by FSR
incf FSR,F ;increment pointer
btfss FSR,7 ;while FSR<0x80 loop
goto CleanB0
return
init_cpu1: Bank1 ;clear RAM(0x00A0-0x00Af)in bank1
movlw INIT_RAM1 ;points to the start of RAM1
movwf FSR
CleanB1: clrf INDF ;clear RAM location pointed by FSR
incf FSR,F ;increment pointer
btfss FSR,4 ;while FSR<0x10 loop
goto CleanB1
return
init_cpu2: Bank2 ;clear RAM(0x0130-0x017f)in bank2
movlw INIT_RAM2 ;points to the start of RAM2
movwf FSR
CleanB2: clrf INDF ;clear RAM location pointed by FSR
incf FSR,F ;increment pointer
btfss FSR,7 ;while FSR<0x80 loop
goto CleanB2
return
;do other initialization here
MainLoop: Bank0 ;select bank0
btfsc Flags2,ReceivedBEL;check if <BEL> character received
call CopyKey ;if so the move received data to key buffer
btfsc Flags,ReceivedCR;check if <CR> character received
call CopyENC ;if so then encrypt received data and move
;to TX Buffer
btfsc Flags,ReceivedLF;check if <LF> character received
call CopyDEC ;if so the decrypt received data and move
;to TX Buffer
;do other stuff here
goto MainLoop ;repeat main loop to check for data
;----------------------------------------------------------------------------
;Set up serial port and buffers.
SetupSerial: Bank1 ;select bank 1
movlw 0xc0 ;set tris bits for TX and RX
iorwf TRISC,F
movlw SPBRG_VAL ;set baud rate
movwf SPBRG
movlw 0x24 ;enable transmission and high baud rate
movwf TXSTA
Bank0 ;select bank0
movlw 0x90 ;enable serial port and reception
movwf RCSTA
call InitTxBuffer ;initialize transmit buffer
call InitRxBuffer ;initialize receive buffer
call InitKeyBuffer
movlw 0xc0 ;enable global and peripheral ints
movwf INTCON
Bank1 ;select bank1
movlw 0x30 ;enable TX and RX interrupts
movwf PIE1
return
;----------------------------------------------------------------------------
;Circular buffer routines.
;----------------------------------------------------------------------------
;Initialize transmit buffer
InitTxBuffer: Bank0
movlw LOW TxBuffer ;take address of transmit buffer
movwf TxStartPtr ;and place in transmit start pointer
movwf TxEndPtr ;and place in transmit end pointer
bcf Flags,TxBufFull ;indicate Tx buffer is not full
bsf Flags,TxBufEmpty ;indicate Tx buffer is empty
return
;----------------------------------------------
;Initialize receive buffer
InitRxBuffer: Bank0
movlw LOW RxBuffer ;take address of receive buffer
movwf RxStartPtr ;and place in receive start pointer
movwf RxEndPtr ;and place in receive end pointer
bcf Flags,RxBufFull ;indicate Rx buffer is not full
bsf Flags,RxBufEmpty ;indicate Rx buffer is empty
return
;----------------------------------------------
;Initialize Key buffer
InitKeyBuffer: Bank0
movlw LOW KeyBuffer ;take address of key buffer
movwf KeyStartPtr ;and place in receive start pointer
movwf KeyEndPtr ;and place in receive end pointer
bcf Flags2,KeyBufFull;indicate Key buffer is not full
bsf Flags2,KeyBufEmpty ;indicate Key buffer is empty
return
;----------------------------------------------
;Add a byte (from WREG) to the end of the key buffer
PutKeyBuffer:
Bank0 ;select bank 0
btfsc Flags2,KeyBufFull;check if buffer full
goto ErrKeyBufFull ;and go handle error if full
BANKISEL KeyBuffer ;bank bit for indirect addressing
movwf BufferData ;save WREG data into BufferData
movf KeyEndPtr,W ;get EndPointer
movwf FSR ;and place into FSR
movf BufferData,W ;get BufferData
movwf INDF ;and store in buffer
;test if buffer pointer needs to wrap around to beginning of buffer memory
movlw LOW KeyBuffer+KEY_BUF_LEN-1 ;get last address of buffer
xorwf KeyEndPtr,W ;and compare with end pointer
movlw LOW KeyBuffer ;load first address of buffer
btfss STATUS,Z ;check if pointer is at last address
incf KeyEndPtr,W ;if not then increment pointer
movwf KeyEndPtr ;store new end pointer value
;test if buffer is full
subwf KeyStartPtr,W ;compare with start pointer
btfsc STATUS,Z ;check if the same
bsf Flags2,KeyBufFull;if so then indicate buffer full
bcf Flags2,KeyBufEmpty ;buffer cannot be empty
Bank0 ;select bank 0
return
;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte
ErrKeyBufFull: Bank0
return ;no save of data because buffer full
;----------------------------------------------
;Add a byte (from WREG) to the end of the transmit buffer
PutTxBuffer: Bank1 ;select bank 1
bcf PIE1,TXIE ;disable transmit interrupt
Bank0 ;select bank 0
btfsc Flags,TxBufFull ;check if buffer full
goto ErrTxBufFull ;and go handle error if full
BANKISEL TxBuffer ;bank bit for indirect addressing
movwf BufferData ;save WREG data into BufferData
movf TxEndPtr,W ;get EndPointer
movwf FSR ;and place into FSR
movf BufferData,W ;get BufferData
movwf INDF ;and store in buffer
;test if buffer pointer needs to wrap around to beginning of buffer memory
movlw LOW TxBuffer+TX_BUF_LEN-1 ;get last address of buffer
xorwf TxEndPtr,W ;and compare with end pointer
movlw LOW TxBuffer ;load first address of buffer
btfss STATUS,Z ;check if pointer is at last address
incf TxEndPtr,W ;if not then increment pointer
movwf TxEndPtr ;store new end pointer value
;test if buffer is full
subwf TxStartPtr,W ;compare with start pointer
btfsc STATUS,Z ;check if the same
bsf Flags,TxBufFull ;if so then indicate buffer full
bcf Flags,TxBufEmpty ;buffer cannot be empty
Bank1 ;select bank 1
bsf PIE1,TXIE ;enable transmit interrupt
Bank0 ;select bank 0
return
;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte
ErrTxBufFull: Bank1 ;select bank 1
bsf PIE1,TXIE ;enable transmit interrupt
Bank0 ;select bank 0
return ;no save of data because buffer full
;----------------------------------------------
;Add a byte (from WREG) to the end of the receive buffer
PutRxBuffer: Bank0 ;select bank 0
btfsc Flags,RxBufFull ;check if buffer full
goto ErrRxBufFull ;and go handle error if full
BANKISEL RxBuffer ;bank bit for indirect addressing
movwf BufferData ;save WREG into BufferData
movf RxEndPtr,W ;get EndPointer
movwf FSR ;and place into FSR
movf BufferData,W ;get BufferData
movwf INDF ;store in buffer
;test if buffer pointer needs to wrap around to beginning of buffer memory
movlw LOW RxBuffer+RX_BUF_LEN-1 ;get last address of buffer
xorwf RxEndPtr,W ;and compare with end pointer
movlw LOW RxBuffer ;load first address of buffer
btfss STATUS,Z ;check if pointer is at last address
incf RxEndPtr,W ;if not then increment pointer
movwf RxEndPtr ;store new end pointer value
;test if buffer is full
subwf RxStartPtr,W ;compare with start pointer
btfsc STATUS,Z ;check if the same
bsf Flags,RxBufFull ;if so then indicate buffer full
bcf Flags,RxBufEmpty ;buffer cannot be empty
return
;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte
ErrRxBufFull: return ;no save of data because buffer full
;----------------------------------------------
;Remove and return (in WREG) the byte at the start of the transmit buffer
GetTxBuffer: Bank0 ;select bank 0
btfsc Flags,TxBufEmpty ;check if transmit buffer empty
goto ErrTxBufEmpty ;and go handle error if empty
BANKISEL TxBuffer ;bank bit for indirect addressing
movf TxStartPtr,W ;get StartPointer
movwf FSR ;and place into FSR
;test if buffer pointer needs to wrap around to beginning of buffer memory
movlw LOW TxBuffer+TX_BUF_LEN-1 ;get last address of buffer
xorwf TxStartPtr,W ;and compare with start pointer
movlw LOW TxBuffer ;load first address of buffer
btfss STATUS,Z ;check if pointer is at last address
incf TxStartPtr,W ;if not then increment pointer
movwf TxStartPtr ;store new pointer value
bcf Flags,TxBufFull ;buffer cannot be full
;test if buffer is now empty
xorwf TxEndPtr,W ;compare start to end
btfsc STATUS,Z ;check if the same
bsf Flags,TxBufEmpty ;if same then buffer will be empty
movf INDF,W ;get data from buffer
return
;error because attempting to read data from an empty buffer
;can do special error handling here - this code simply returns zero
ErrTxBufEmpty: retlw 0 ;tried to read empty buffer
;----------------------------------------------
;Remove and return (in WREG) the byte at the start of the receive buffer
GetRxBuffer: Bank0 ;select bank 0
btfsc Flags,RxBufEmpty ;check if receive buffer empty
goto ErrRxBufEmpty ;and go handle error if empty
Bank1 ;select bank 1
bcf PIE1,RCIE ;disable receive interrupt
Bank0 ;select bank 0
BANKISEL RxBuffer ;bank bit for indirect addressing
movf RxStartPtr,W ;get StartPointer
movwf FSR ;and place into FSR
;test if buffer pointer needs to wrap around to beginning of buffer memory
movlw LOW RxBuffer+RX_BUF_LEN-1 ;get last address of buffer
xorwf RxStartPtr,W ; and compare with start pointer
movlw LOW RxBuffer ;load first address of buffer
btfss STATUS,Z ;check if pointer is at last address
incf RxStartPtr,W ;if not then increment pointer
movwf RxStartPtr ;store new pointer value
bcf Flags,RxBufFull ;buffer cannot be full
;test if buffer is now empty
xorwf RxEndPtr,W ;compare start to end
btfsc STATUS,Z ;check if the same
bsf Flags,RxBufEmpty ;if same then buffer will be empty
movf INDF,W ;get data from buffer
Bank1 ;select bank 1
bsf PIE1,RCIE ;enable receive interrupt
Bank0 ;select bank 0
return
;error because attempting to read data from an empty buffer
;can do special error handling here - this code simply returns zero
ErrRxBufEmpty: Bank1 ;select bank 1
bsf PIE1,RCIE ;enable receive interrupt
Bank0 ;select bank 0
retlw 0 ;tried to read empty buffer
;----------------------------------------------------------------------------
;Get receive buffer data and move to Key buffer
CopyKey: Bank0 ;select bank 0
bcf Flags2,ReceivedBEL ;clear <BEL> received indicator
Copy1: btfsc Flags,RxBufEmpty ;check if Rx buffer is empty
return ;if so then return
call GetRxBuffer ;get data from receive buffer
call PutKeyBuffer ;put data in transmit buffer
goto Copy1 ;if not the same then move another byte
;----------------------------------------------------------------------------
;Encrypt receive buffer data and move to transmit buffer
CopyENC: Bank0 ;select bank 2
movlw 0xa0 ;take address of transmit buffer
movwf TxStartPtr ;and place in transmit start pointer
movwf TxEndPtr ;and transmit end pointer
Bank2
call set_test_key ;move constant key by user to key buffer
;that is overwritten during encryption
call encrypt ;encrypt RX buffer data
Bank0
bcf Flags,ReceivedCR;clear <CR> received indicator
Copy2: btfsc Flags,RxBufEmpty;check if Rx buffer is empty
return ;if so then return
call GetRxBuffer ;get data from receive buffer
call PutTxBuffer ;put data in transmit buffer
goto Copy2 ;if not the same then move another byte
;----------------------------------------------------------------------------
;Decrypt receive buffer data and move to transmit buffer
CopyDEC: Bank0 ;select bank 2
movlw 0xa0 ;take address of transmit buffer
movwf TxStartPtr ;and place in transmit start pointer
movwf TxEndPtr ;and transmit end pointer
Bank2
call set_test_key ;move constant key by user to key buffer
;that is overwritten during encryption
call init_decryption_key;calculate initial decryption key
call decrypt ;decrypt RX buffer data
Bank0
bcf Flags,ReceivedLF;clear <LF> received indicator
Copy3: btfsc Flags,RxBufEmpty;check if Rx buffer is empty
return ;if so then return
call GetRxBuffer ;get data from receive buffer
call PutTxBuffer ;put data in transmit buffer
goto Copy3 ;if not the same then move another byte
;----------------------------------------------------------------------------
;Load user input 16 byte key into key test block
set_test_key:
movf KeyBuffer+0x0,W
movwf key+0x0
movf KeyBuffer+0x1,W
movwf key+0x1
movf KeyBuffer+0x2,W
movwf key+0x2
movf KeyBuffer+0x3,W
movwf key+0x3
movf KeyBuffer+0x4,W
movwf key+0x4
movf KeyBuffer+0x5,W
movwf key+0x5
movf KeyBuffer+0x6,W
movwf key+0x6
movf KeyBuffer+0x7,W
movwf key+0x7
movf KeyBuffer+0x8,W
movwf key+0x8
movf KeyBuffer+0x9,W
movwf key+0x9
movf KeyBuffer+0xA,W
movwf key+0xA
movf KeyBuffer+0xB,W
movwf key+0xB
movf KeyBuffer+0xC,W
movwf key+0xC
movf KeyBuffer+0xD,W
movwf key+0xD
movf KeyBuffer+0xE,W
movwf key+0xE
movf KeyBuffer+0xF,W
movwf key+0xF
return
; ********************* KEY_ADDITION ****************************
; This procedure makes: block ^= key ( ^= means block = block XOR key)
; Input: None
; Outup:
; Globals: block, key
; OBS: Implemented without a loop to increase speed
; ***************************************************************
key_addition:
movf key+0x0,w ; block[0] ^= key[0];
xorwf block+0x0,f
movf key+0x1,w ; block[1] ^= key[1];
xorwf block+0x1,f
movf key+0x2,w ; block[2] ^= key[2];
xorwf block+0x2,f
movf key+0x3,w ; block[3] ^= key[3];
xorwf block+0x3,f
movf key+0x4,w ; block[4] ^= key[4];
xorwf block+0x4,f
movf key+0x5,w ; block[5] ^= key[5];
xorwf block+0x5,f
movf key+0x6,w ; block[6] ^= key[6];
xorwf block+0x6,f
movf key+0x7,w ; block[7] ^= key[7];
xorwf block+0x7,f
movf key+0x8,w ; block[8] ^= key[8];
xorwf block+0x8,f
movf key+0x9,w ; block[9] ^= key[9];
xorwf block+0x9,f
movf key+0x0A,w ; block[10] ^= key[10];
xorwf block+0x0A,f
movf key+0x0B,w ; block[11] ^= key[11];
xorwf block+0x0B,f
movf key+0x0C,w ; block[12] ^= key[12];
xorwf block+0x0C,f
movf key+0x0D,w ; block[13] ^= key[13];
xorwf block+0x0D,f
movf key+0x0E,w ; block[14] ^= key[14];
xorwf block+0x0E,f
movf key+0x0F,w ; block[15] ^= key[15];
xorwf block+0x0F,f
return
; *********************** SUBSTITUTION_S **************************
; This procedure makes: block[i] = S_box[block[i]]
;
; Input:
; Outup:
; Globals: aux,block,FSR,PCLATH
; *****************************************************************
substitution_S: ; implements the direct substitution
movlw HIGH S_table ; selects segment
movwf PCLATH ;
; it works like: for i(0....15)
put_s_table_b0:
movlw D'99' ; if (block[i]==0) --> block[i]=99D
movf block+0x0,f
btfsc STATUS,Z
goto put_b0
decf block+0x0,w
call S_table ; else block[i] = S_table[block[i]-1]
put_b0:
movwf block+0x0
put_s_table_b1:
movlw D'99' ;
movf block+0x1,f
btfsc STATUS,Z
goto put_b1
decf block+0x1,w
call S_table ;
put_b1:
movwf block+0x1
put_s_table_b2:
movlw D'99' ;
movf block+0x2,f
btfsc STATUS,Z
goto put_b2
decf block+0x2,w
call S_table ;
put_b2:
movwf block+0x2
put_s_table_b3:
movlw D'99' ;
movf block+0x3,f
btfsc STATUS,Z
goto put_b3
decf block+0x3,w
call S_table ;
put_b3:
movwf block+0x3
put_s_table_b4:
movlw D'99' ;
movf block+0x4,f
btfsc STATUS,Z
goto put_b4
decf block+0x4,w
call S_table ;
put_b4:
movwf block+0x4
put_s_table_b5:
movlw D'99' ;
movf block+0x5,f
btfsc STATUS,Z
goto put_b5
decf block+0x5,w
call S_table ;
put_b5:
movwf block+0x5
put_s_table_b6:
movlw D'99' ;
movf block+0x6,f
btfsc STATUS,Z
goto put_b6
decf block+0x6,w
call S_table ;
put_b6:
movwf block+0x6
put_s_table_b7:
movlw D'99' ;
movf block+0x7,f
btfsc STATUS,Z
goto put_b7
decf block+0x7,w
call S_table ;
put_b7:
movwf block+0x7
put_s_table_b8:
movlw D'99' ;
movf block+0x8,f
btfsc STATUS,Z
goto put_b8
decf block+0x8,w
call S_table ;
put_b8:
movwf block+0x8
put_s_table_b9:
movlw D'99' ;
movf block+0x9,f
btfsc STATUS,Z
goto put_b9
decf block+0x9,w
call S_table ;
put_b9:
movwf block+0x9
put_s_table_bA:
movlw D'99' ;
movf block+0xA,f
btfsc STATUS,Z
goto put_bA
decf block+0xA,w
call S_table ;
put_bA:
movwf block+0xA
put_s_table_bB:
movlw D'99' ;
movf block+0xB,f
btfsc STATUS,Z
goto put_bB
decf block+0xB,w
call S_table ;
put_bB:
movwf block+0xB
put_s_table_bC:
movlw D'99' ;
movf block+0xC,f
btfsc STATUS,Z
goto put_bC
decf block+0xC,w
call S_table ;
put_bC:
movwf block+0xC
put_s_table_bD:
movlw D'99' ;
movf block+0xD,f
btfsc STATUS,Z
goto put_bD
decf block+0xD,w
call S_table ;
put_bD:
movwf block+0xD
put_s_table_bE:
movlw D'99' ;
movf block+0xE,f
btfsc STATUS,Z
goto put_bE
decf block+0xE,w
call S_table ;
put_bE:
movwf block+0xE
put_s_table_bF:
movlw D'99' ;
movf block+0xF,f
btfsc STATUS,Z
goto put_bF
decf block+0xF,w
call S_table ;
put_bF:
movwf block+0xF
return
; *********************** SUBSTITUTION_Si *************************
; This procedure makes: block[i] = Si_box[block[i]].
; This is the inverse mapping because:
;
; b = S_box[a] and
; a = Si_box[b]
;
; Input:
; Outup:
; Globals: aux,block,FSR,PCLATH
; *****************************************************************
substitution_Si: ; implements the inverse substitution
movlw HIGH Si_table ; selects segment
movwf PCLATH ;
; it works like: for i(0....15)
put_si_table_b0:
movlw D'82' ; if (block[i]==0) block[]=82D
movf block+0x0,f
btfsc STATUS,Z
goto putsi_b0
decf block+0x0,w
call Si_table ; else block[i] = Si_table[block[i]-1]
putsi_b0:
movwf block+0x0
put_si_table_b1:
movlw D'82' ;
movf block+0x1,f
btfsc STATUS,Z
goto putsi_b1
decf block+0x1,w
call Si_table ;
putsi_b1:
movwf block+0x1
put_si_table_b2:
movlw D'82' ;
movf block+0x2,f
btfsc STATUS,Z
goto putsi_b2
decf block+0x2,w
call Si_table ;
putsi_b2:
movwf block+0x2
put_si_table_b3:
movlw D'82' ;
movf block+0x3,f
btfsc STATUS,Z
goto putsi_b3
decf block+0x3,w
call Si_table ;
putsi_b3:
movwf block+0x3
put_si_table_b4:
movlw D'82' ;
movf block+0x4,f
btfsc STATUS,Z
goto putsi_b4
decf block+0x4,w
call Si_table ;
putsi_b4:
movwf block+0x4
put_si_table_b5:
movlw D'82' ;
movf block+0x5,f
btfsc STATUS,Z
goto putsi_b5
decf block+0x5,w
call Si_table ;
putsi_b5:
movwf block+0x5
put_si_table_b6:
movlw D'82' ;
movf block+0x6,f
btfsc STATUS,Z
goto putsi_b6
decf block+0x6,w
call Si_table ;
putsi_b6:
movwf block+0x6
put_si_table_b7:
movlw D'82' ;
movf block+0x7,f
btfsc STATUS,Z
goto putsi_b7
decf block+0x7,w
call Si_table ;
putsi_b7:
movwf block+0x7
put_si_table_b8:
movlw D'82' ;
movf block+0x8,f
btfsc STATUS,Z
goto putsi_b8
decf block+0x8,w
call Si_table ;
putsi_b8:
movwf block+0x8
put_si_table_b9:
movlw D'82' ;
movf block+0x9,f
btfsc STATUS,Z
goto putsi_b9
decf block+0x9,w
call Si_table ;
putsi_b9:
movwf block+0x9
put_si_table_bA:
movlw D'82' ;
movf block+0xA,f
btfsc STATUS,Z
goto putsi_bA
decf block+0xA,w
call Si_table ;
putsi_bA:
movwf block+0xA
put_si_table_bB:
movlw D'82' ;
movf block+0xB,f
btfsc STATUS,Z
goto putsi_bB
decf block+0xB,w
call Si_table ;
putsi_bB:
movwf block+0xB
put_si_table_bC:
movlw D'82' ;
movf block+0xC,f
btfsc STATUS,Z
goto putsi_bC
decf block+0xC,w
call Si_table ;
putsi_bC:
movwf block+0xC
put_si_table_bD:
movlw D'82' ;
movf block+0xD,f
btfsc STATUS,Z
goto putsi_bD
decf block+0xD,w
call Si_table ;
putsi_bD:
movwf block+0xD
put_si_table_bE:
movlw D'82' ;
movf block+0xE,f
btfsc STATUS,Z
goto putsi_bE
decf block+0xE,w
call Si_table ;
putsi_bE:
movwf block+0xE
put_si_table_bF:
movlw D'82' ;
movf block+0xF,f
btfsc STATUS,Z
goto putsi_bF
decf block+0xF,w
call Si_table ;
putsi_bF:
movwf block+0xF
return
; *********************** ENC_SHIFT_ROW and DEC_SHIFT_ROW *******************************
; These procedures shift rows (1,2 and 3 but NOT 0) a variable
; amount on the direction (encryption or decryption)
; Input:
; Outup: shifted block
; Globals: aux, block, row_vector
; OBS:
; As defined in the AES Proposal: Rijndael document,
; this procedure ciclically shifts rows 1,2 and 3 by offsets
; that for 128 bits blocks and key are defined as:
; Cipher: row1 --> 1, row2 -->2 and row3 -->3
; Decipher: row1 --> 3, row2 -->2 and row3 -->1.
;
; It is also equivalent to the folowing reference
; C code designed by Paulo Barreto and Vincent Rijmen:
; ** parameter "d" gives the direction: 0 = cipher
; 1 = decipher
;
; static word8 shifts[3][4][2] = {0, 0,
; 1, 3,
; 2, 2,
; 3, 1,
;
; 0, 0,
; 1, 5,
; 2, 4,
; 3, 3,
;
; 0, 0,
; 1, 7,
; 3, 5,
; 4, 4};
;
; void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC)
; {
; /* Row 0 remains unchanged * The other three rows are shifted a variable amount*/
; word8 tmp[MAXBC];
; int i, j;
;
; for(i = 1; i < 4; i++)
; {
; for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC];
; for(j = 0; j < BC; j++) a[i][j] = tmp[j];
; }
; }
;
; Obs: BC = 4, SC=0
; d=0 -> encription
; d=1 -> encription
;
; ***************************************************************************************
enc_shift_row:
; Rotates left row 1 one position
movf block+0x1,w
movwf aux
movf block+0x5,w ;
movwf block+0x1
movf block+0x9,w ;
movwf block+0x5
movf block+0xD,w ;
movwf block+0x9
movf aux,w
movwf block+0xD ;
; Rotates left row 2 two positions from position block+0x0A
movf block+0x2,w
movwf aux
movf block+0x6,w
movwf aux1
movf block+0xA,w
movwf block+0x2
movf block+0xE,w
movwf block+0x6
movf aux,w
movwf block+0xA
movf aux1,w
movwf block+0xE
; Rotates left row 3 three positions from block+0xB
movf block+0xF,w
movwf aux
movf block+0xB,w
movwf block+0xF
movf block+0x7,w
movwf block+0xB
movf block+0x3,w
movwf block+0x7
movf aux,w
movwf block+0x3
return
;****************************************************************************************
dec_shift_row:
; Rotates right row 1 one position
movf block+0xD,w
movwf aux
movf block+0x9,w
movwf block+0xD
movf block+0x5,w
movwf block+0x9
movf block+0x1,w
movwf block+0x5
movf aux,w
movwf block+0x1
; Rotates right row 2 two positions
movf block+0xA,w
movwf aux
movf block+0xE,w
movwf aux1
movf block+0x2,w
movwf block+0xA
movf block+0x6,w
movwf block+0xE
movf aux,w
movwf block+0x2
movf aux1,w
movwf block+0x6
; Rotates right row 3 one positions
movf block+0x3,w
movwf aux
movf block+0x7,w
movwf block+0x3
movf block+0xB,w
movwf block+0x7
movf block+0xF,w
movwf block+0xB
movf aux,w
movwf block+0xF
return
; *********************** INV_MIX_COLUMN ************************
; This procedure calculates the inverse mix column of the state
; (block with partial results); it is equivalent to the
; multiplication of the block taken in rows of an 4x4 matrix by
; the following matrix (over GF2)
;
; 0xE 0xB 0xD 0x9
; 0xB 0xD 0x9 0xE
; 0xD 0x9 0xE 0xB
; 0x9 0xE 0xB 0xD
;
; The equivalent C code designed by Paulo Barreto and Vincent Rijmen:
;
; void InvMixColumn(word8 a[4][MAXBC], word8 BC)
; {/* Mix the four bytes of every column in a linear way
; * This is the opposite operation of Mixcolumn */
; word8 b[4][MAXBC];
; int i, j;
;
; for(j = 0; j < BC; j++)
; for(i = 0; i < 4; i++);
; b[i][j] = mul(0xe,a[i][j])
; ^ mul(0xb,a[(i + 1) % 4][j])
; ^ mul(0xd,a[(i + 2) % 4][j])
; ^ mul(0x9,a[(i + 3) % 4][j]);
; for(i = 0; i < 4; i++)
; for(j = 0; j < BC; j++) a[i][j] = b[i][j];
; }
;
; Obs: BC=4
;
;
; Input: block
; Outup: block
; Globals: aux,aux1,aux2,aux3
;
; OBS:This implementation uses the following optimized equivalent
; structure: (as seen in Geoffrey Keating's implementation)
;
; aux = block[i+0] ^ block[i+0x1] ^ block[i+0x2] ^ block[i+0x3];
; aux1 = xtime(block[i+0x0] ^ block[i+0x2]);
; aux2 = xtime(block[i+1] ^ block[i+0x3]);
; aux3 = xtime( xtime( aux1 ^ aux2 ) ^ aux;
; d0 = xtime(block[i+0x0]^block[i+0x1] ^ aux1);
; d1 = xtime(block[i+0x1] ^ block[i+0x2] ^ aux2);
; d2 = xtime(block[i+0x2] ^ block[i+0xC] ^ aux1);
; Block[i+0x0] ^= d0 ^ aux3;
; Block[i+0x1] ^= d1 ^ aux3;
; block[i+0x2] ^= d2 ^ aux3;
; Block[i+0x3] = block[i+0x0] ^ block[i+1] ^ block[i+2] ^ aux;
;
; ***************************************************************
inv_mix_column:
; **** it begins by calculating inv_mix_column for the FIRST column ****
movf block+0x0,w ; aux = block+0x0 ^ block+0x1 ^ block+0x2 ^ block+0x3
xorwf block+0x1,w
xorwf block+0x2,w
xorwf block+0x3,w
movwf aux
movf block+0x0,w ; aux1 = xtime(block+0x0 ^ block+0x2)
xorwf block+0x2,w
movwf aux1
movlw 0x1B
bcf STATUS,C
rlf aux1,f
btfsc STATUS,C
xorwf aux1,f
movf block+0x1,w ; aux2 = xtime(block+0x1 ^ block+0x3)
xorwf block+0x3,w
movwf aux2
movlw 0x1B
bcf STATUS,C
rlf aux2,f
btfsc STATUS,C
xorwf aux2,f
movf aux1,w ; aux3 = xtime(xtime(block+0x1 ^ block+0x2)) ^ aux
xorwf aux2,w
movwf aux3
movlw 0x1B
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
movf aux,w
xorwf aux3,f
movf block+0x0,w ; d0 = xtime(block+0x0 ^ block+0x1 ^ aux1)
xorwf block+0x1,w
xorwf aux1,w
movwf d0
movlw 0x1B
bcf STATUS,C
rlf d0,f
btfsc STATUS,C
xorwf d0,f
movf block+0x1,w ; d1 = xtime(block+0x1 ^ block+0x2 ^ aux2)
xorwf block+0x2,w
xorwf aux2,w
movwf d1
movlw 0x1B
bcf STATUS,C
rlf d1,f
btfsc STATUS,C
xorwf d1,f
movf block+0x2,w ; d2 = xtime(block+0x2 ^ block+0x3 ^ aux1)
xorwf block+0x3,w
xorwf aux1,w
movwf d2
movlw 0x1B
bcf STATUS,C
rlf d2,f
btfsc STATUS,C
xorwf d2,f
movf d0,w ; block+0 ^= d0 ^ aux3
xorwf aux3,w
xorwf block+0x0,f
movf d1,w ; block+1 ^= d1 ^ aux3
xorwf aux3,w
xorwf block+0x1,f
movf d2,w ; block+2 ^= d2 ^ aux3
xorwf aux3,w
xorwf block+0x2,f
movf block+0x0,w ; block+3 = block+0 ^ block+1 ^ block+2 ^ aux
xorwf block+0x1,w
xorwf block+0x2,w
xorwf aux,w
movwf block+0x3
; ******* inv_mix_column for the SECOND column *******
; It uses the same structure used in the first column
movf block+0x4,w ;
xorwf block+0x5,w
xorwf block+0x6,w
xorwf block+0x7,w
movwf aux
movf block+0x4,w ;
xorwf block+0x6,w
movwf aux1
movlw 0x1B
bcf STATUS,C
rlf aux1,f
btfsc STATUS,C
xorwf aux1,f
movf block+0x5,w ;
xorwf block+0x7,w
movwf aux2
movlw 0x1B
bcf STATUS,C
rlf aux2,f
btfsc STATUS,C
xorwf aux2,f
movf aux1,w ;
xorwf aux2,w
movwf aux3
movlw 0x1B
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
movf aux,w
xorwf aux3,f
movf block+0x4,w ;
xorwf block+0x5,w
xorwf aux1,w
movwf d0
movlw 0x1B
bcf STATUS,C
rlf d0,f
btfsc STATUS,C
xorwf d0,f
movf block+0x5,w ;
xorwf block+0x6,w
xorwf aux2,w
movwf d1
movlw 0x1B
bcf STATUS,C
rlf d1,f
btfsc STATUS,C
xorwf d1,f
movf block+0x6,w ;
xorwf block+0x7,w
xorwf aux1,w
movwf d2
movlw 0x1B
bcf STATUS,C
rlf d2,f
btfsc STATUS,C
xorwf d2,f
movf d0,w ;
xorwf aux3,w
xorwf block+0x4,f
movf d1,w ;
xorwf aux3,w
xorwf block+0x5,f
movf d2,w ;
xorwf aux3,w
xorwf block+0x6,f
movf block+0x4,w ;
xorwf block+0x5,w
xorwf block+0x6,w
xorwf aux,w
movwf block+0x7
; ******* inv_mix_column for the THIRD column *******
; It uses the same structure used in the first column
movf block+0x8,w
xorwf block+0x9,w
xorwf block+0xA,w
xorwf block+0xB,w
movwf aux
movf block+0x8,w ;
xorwf block+0xA,w
movwf aux1
movlw 0x1B
bcf STATUS,C
rlf aux1,f
btfsc STATUS,C
xorwf aux1,f
movf block+0x9,w ;
xorwf block+0xB,w
movwf aux2
movlw 0x1B
bcf STATUS,C
rlf aux2,f
btfsc STATUS,C
xorwf aux2,f
movf aux1,w ;
xorwf aux2,w
movwf aux3
movlw 0x1B
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
movf aux,w
xorwf aux3,f
movf block+0x8,w ;
xorwf block+0x9,w
xorwf aux1,w
movwf d0
movlw 0x1B
bcf STATUS,C
rlf d0,f
btfsc STATUS,C
xorwf d0,f
movf block+0x9,w ;
xorwf block+0xA,w
xorwf aux2,w
movwf d1
movlw 0x1B
bcf STATUS,C
rlf d1,f
btfsc STATUS,C
xorwf d1,f
movf block+0xA,w ;
xorwf block+0xB,w
xorwf aux1,w
movwf d2
movlw 0x1B
bcf STATUS,C
rlf d2,f
btfsc STATUS,C
xorwf d2,f
movf d0,w ;
xorwf aux3,w
xorwf block+0x8,f
movf d1,w ;
xorwf aux3,w
xorwf block+0x9,f
movf d2,w ;
xorwf aux3,w
xorwf block+0xA,f
movf block+0x8,w ;
xorwf block+0x9,w
xorwf block+0xA,w
xorwf aux,w
movwf block+0xB
; ******* inv_mix_column for the LAST (FOURTH) column *******
; It uses the same structure used in the first column
movf block+0xC,w ;
xorwf block+0xD,w
xorwf block+0xE,w
xorwf block+0xF,w
movwf aux
movf block+0xC,w ;
xorwf block+0xE,w
movwf aux1
movlw 0x1B
bcf STATUS,C
rlf aux1,f
btfsc STATUS,C
xorwf aux1,f
movf block+0xD,w ;
xorwf block+0xF,w
movwf aux2
movlw 0x1B
bcf STATUS,C
rlf aux2,f
btfsc STATUS,C
xorwf aux2,f
movf aux1,w ;
xorwf aux2,w
movwf aux3
movlw 0x1B
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
movf aux,w
xorwf aux3,f
movf block+0xC,w ;
xorwf block+0xD,w
xorwf aux1,w
movwf d0
movlw 0x1B
bcf STATUS,C
rlf d0,f
btfsc STATUS,C
xorwf d0,f
movf block+0xD,w ;
xorwf block+0xE,w
xorwf aux2,w
movwf d1
movlw 0x1B
bcf STATUS,C
rlf d1,f
btfsc STATUS,C
xorwf d1,f
movf block+0xE,w ;
xorwf block+0xF,w
xorwf aux1,w
movwf d2
movlw 0x1B
bcf STATUS,C
rlf d2,f
btfsc STATUS,C
xorwf d2,f
movf d0,w ;
xorwf aux3,w
xorwf block+0xC,f
movf d1,w ;
xorwf aux3,w
xorwf block+0xD,f
movf d2,w ;
xorwf aux3,w
xorwf block+0xE,f
movf block+0xC,w ;
xorwf block+0xD,w
xorwf block+0xE,w
xorwf aux,w
movwf block+0xF
return
; ************************* MIX_COLUMN ************************
; This procedure calculates the direct mix column of the state
; (block with partial results); it is equivalent to the
; multiplication of the block taken in rows of an 4x4 matrix by
; the following matrix (over GF2)
;
; 0x2 0x3 0x1 0x1
; 0x3 0x1 0x1 0x2
; 0x1 0x1 0x2 0x3
; 0x1 0x2 0x3 0x1
;
; The equivalent C code designed by Paulo Barreto and Vincent Rijmen:
;
; Obs: BC=4
;
; oid MixColumn(word8 a[4][MAXBC], word8 BC)
; {/* Mix the four bytes of every column in a linear way*/
; word8 b[4][MAXBC];
; int i, j;
;
; for(j = 0; j < BC; j++)
; for(i = 0; i < 4; i++)
; b[i][j] = mul(2,a[i][j])
; ^ mul(3,a[(i + 1) % 4][j])
; ^ a[(i + 2) % 4][j]
; ^ a[(i + 3) % 4][j];
; for(i = 0; i < 4; i++)
; for(j = 0; j < BC; j++) a[i][j] = b[i][j];
; }
;
; Obs: BC=4
;
;
; Input:
; Outup:
; Globals:
; ***************************************************************
mix_column:
; begins with the mix of column 0
movf block+0x0,w
xorwf block+0x1,w
movwf aux1 ; aux1 = block+0x0 ^ block+0x1
xorwf block+0x2,w
xorwf block+0x3,w
movwf aux ; aux = block+0x0 ^ block+0x1 ^ block+0x2 ^ block+0x3
movf block+0x1,w ; aux2 = block+0x1 ^ block+0x2
xorwf block+0x2,w
movwf aux2
movf block+0x2,w ; aux3 = block+0x2 ^ block+0x3
xorwf block+0x3,w
movwf aux3
call calc_xtimes ; aux = xtime(aux), aux1 = xtime(aux1), aux2 = xtime(aux2), aux3 = xtime(aux3)
movf aux,w ; block+0x0 ^= aux ^ aux1
xorwf aux1,w
xorwf block+0x0,f
movf aux,w ; block+0x1 ^= aux ^ aux2
xorwf aux2,w
xorwf block+0x1,f
movf aux,w ; block+0x2 ^= aux ^ aux3
xorwf aux3,w
xorwf block+0x2,f
movf block+0x0,w ; block+0x3 = block+0x1 ^ block+0x2 ^ block+0x2 ^ aux
xorwf block+0x1,w
xorwf block+0x2,w
xorwf aux,w
movwf block+0x3
; mix of column 1
movf block+0x4,w
xorwf block+0x5,w
movwf aux1 ;
xorwf block+0x6,w
xorwf block+0x7,w
movwf aux
movf block+0x5,w
xorwf block+0x6,w
movwf aux2
movf block+0x6,w
xorwf block+0x7,w
movwf aux3
call calc_xtimes
movf aux,w
xorwf aux1,w
xorwf block+0x4,f
movf aux,w
xorwf aux2,w
xorwf block+0x5,f
movf aux,w
xorwf aux3,w
xorwf block+0x6,f
movf block+0x4,w
xorwf block+0x5,w
xorwf block+0x6,w
xorwf aux,w
movwf block+0x7
; mix of column 2
movf block+0x8,w
xorwf block+0x9,w
movwf aux1 ;
xorwf block+0xA,w
xorwf block+0xB,w
movwf aux
movf block+0x9,w
xorwf block+0xA,w
movwf aux2
movf block+0xA,w
xorwf block+0xB,w
movwf aux3
call calc_xtimes
movf aux,w
xorwf aux1,w
xorwf block+0x8,f
movf aux,w
xorwf aux2,w
xorwf block+0x9,f
movf aux,w
xorwf aux3,w
xorwf block+0xA,f
movf block+0x8,w
xorwf block+0x9,w
xorwf block+0xA,w
xorwf aux,w
movwf block+0xB
; mix of column 3
movf block+0xC,w
xorwf block+0xD,w
movwf aux1 ;
xorwf block+0xE,w
xorwf block+0xF,w
movwf aux
movf block+0xD,w
xorwf block+0xE,w
movwf aux2
movf block+0xE,w
xorwf block+0xF,w
movwf aux3
call calc_xtimes
movf aux,w
xorwf aux1,w
xorwf block+0xC,f
movf aux,w
xorwf aux2,w
xorwf block+0xD,f
movf aux,w
xorwf aux3,w
xorwf block+0xE,f
movf block+0xC,w
xorwf block+0xD,w
xorwf block+0xE,w
xorwf aux,w
movwf block+0xF
return
calc_xtimes:
movlw 0x1B
bcf STATUS,C
rlf aux1,f
btfsc STATUS,C
xorwf aux1,f
bcf STATUS,C
rlf aux2,f
btfsc STATUS,C
xorwf aux2,f
bcf STATUS,C
rlf aux3,f
btfsc STATUS,C
xorwf aux3,f
return
; ********************* ENC_KEY_SCHEDULE **********************
; This procedure takes the actual key and generates a new one.
; The equivalent C code fragment as designed by Paulo Barreto
; and Vincent Rijmen: (key taken as a 4x4 matrix)
;
; word32 rcon[30] = {0x01,0x02, 0x04, 0x08,
; 0x10, 0x20, 0x40, 0x80,
; 0x1b, 0x36, 0x6c, 0xd8,
; 0xab, 0x4d, 0x9a, 0x2f,
; 0x5e, 0xbc, 0x63, 0xc6,
; 0x97, 0x35, 0x6a, 0xd4,
; 0xb3, 0x7d, 0xfa, 0xef,
; 0xc5, 0x91, };
;
;
; rconpointer=0;
; for(i = 0; i < 4; i++)
; key[i][0] ^= S[key[(i+1)%4][KC-1]];
; key[0][0] ^= rcon[rconpointer++];
; for(j = 1; j < KC; j++)
; for(i = 0; i < 4; i++)
; key[i][j] ^= key[i][j-1];
;
;
; Input: key
; Outup:
; Globals: aux,rcon
; ***************************************************************
enc_key_schedule:
call calc_s_table_based_values
movf rcon,w ; key[0] ^= rcon
xorwf key,f
bcf STATUS,C
rlf rcon,f ; rcon = xtime(rcon)
btfss STATUS,C
goto complete_round
movlw 0x1B
movwf rcon
complete_round:
movf key+0x0,w ; This is equivalent to the
xorwf key+0x4,f ; XOR of each column with the
; previous one
movf key+0x1,w
xorwf key+0x5,f
; first column1 ^= column0
movf key+0x2,w
xorwf key+0x6,f
movf key+0x3,w
xorwf key+0x7,f
; column2 ^= column1
movf key+0x4,w
xorwf key+0x8,f
movf key+0x5,w
xorwf key+0x9,f
movf key+0x6,w
xorwf key+0xA,f
movf key+0x7,w
xorwf key+0xB,f
; column3 ^= column2
movf key+0x8,w
xorwf key+0xC,f
movf key+0x9,w
xorwf key+0xD,f
movf key+0xA,w
xorwf key+0xE,f
movf key+0xB,w
xorwf key+0xF,f
return
calc_s_table_based_values:
movlw HIGH S_table ; set the table segment
movwf PCLATH
movf key+0xD,w
btfss STATUS,Z
goto put_S_table_0xD
movlw D'99'
xorwf key+0x0,f
goto read_key_0xE
put_S_table_0xD:
decf key+0xD,w ; key[0x0] ^= s_box[key[0xD]]
call S_table
xorwf key+0x0,f
read_key_0xE:
movf key+0xE,w
btfss STATUS,Z
goto put_S_table_0xE
movlw D'99'
xorwf key+0x1,f
goto read_key_0xF
put_S_table_0xE:
decf key+0xE,w ; key[0x1] ^= s_box[key[0xE]]
call S_table
xorwf key+0x1,f
read_key_0xF:
movf key+0xF,w
btfss STATUS,Z
goto put_S_table_0xF
movlw D'99'
xorwf key+0x2,f
goto read_key_0xC
put_S_table_0xF:
decf key+0xF,w ; key[0x2] ^= s_box[key[0xF]]
call S_table
xorwf key+0x2,f
read_key_0xC:
movf key+0xC,w
btfss STATUS,Z
goto put_S_table_0xC
movlw D'99'
xorwf key+0x3,f
return ;
put_S_table_0xC:
decf key+0xC,w ; key[0x3] ^= s_box[key[0xC]]
call S_table
xorwf key+0x3,f
return
; *********************** DEC_KEY_SCHEDULE **********************
; This procedure takes the actual key and generates a new one in
; the exact inverse sequence used by enc_key_schedule function
;
;
; Input: key
; Outup:
; Globals: aux,rcon
; ***************************************************************
dec_key_schedule:
;
;first column3 ^= column2
movf key+0x8,w
xorwf key+0xC,f
movf key+0x09,w
xorwf key+0x0D,f
movf key+0x0A,w
xorwf key+0x0E,f
movf key+0x0B,w
xorwf key+0x0F,f
;column2 ^= column1
movf key+0x04,w
xorwf key+0x08,f
movf key+0x05,w
xorwf key+0x09,f
movf key+0x06,w
xorwf key+0x0A,f
movf key+0x07,w
xorwf key+0x0B,f
;first column1 ^= column0
movf key+0x00,w
xorwf key+0x04,f
movf key+0x01,w
xorwf key+0x05,f
movf key+0x02,w
xorwf key+0x06,f
movf key+0x03,w
xorwf key+0x07,f
movf rcon,w ; key[ox0] ^= rcon, rcon>>=1, if carry rcon = 0x80
xorwf key,f
bcf STATUS,C ; this is equivalent to the
rrf rcon,f ; read of rcon table
btfss STATUS,C ;
goto complete_decrypt_round
movlw 0x80
movwf rcon
complete_decrypt_round:
goto calc_s_table_based_values
; ************************** DECRYPT ******************************
; This procedure decipher the plain text in block using key
; Inputs: The encrypted text in block[],
; The decipher_key in key[]; this key is NOT the
; original cipher key used to cipher the plain text,
; but the scheduled original.
; Outups: The plain text in block
; The original cipher key in key[]
; OBS: This implementation follows as possible the original
; structure and function names used by the reference
; implementation of AES
; *****************************************************************
decrypt:
movlw 0x36
movwf rcon ; RCON initialization
call key_addition ; initial key addition
movlw ROUNDS
movwf round_counter ;
goto dec_first_round
loop_decrypt:
call inv_mix_column
dec_first_round:
call substitution_Si ;
call dec_shift_row
call dec_key_schedule
call key_addition ;
decfsz round_counter,f
goto loop_decrypt
return
; ************************** ENCRYPT ******************************
; This procedure cipher the plain text in block using key
; Inputs: The plain_text in block[]
; The cipher_key in key[]
; Outups: The ciphered text in block
; The rounded (decipher) key in key[]
; OBS: This implementation follows as possible the original
; structure and function names used by the reference
; implementation of AES
; *****************************************************************
encrypt:
movlw 0x01
movwf rcon ; RCON initialization
call key_addition ; initial key addition
movlw ROUNDS ; start the round counter for the loop
movwf round_counter
loop_encrypt:
call substitution_S ;
call enc_shift_row
decf round_counter,w
btfsc STATUS,Z
goto last_round
call mix_column
last_round:
call enc_key_schedule
call key_addition ; key addition
decfsz round_counter,f
goto loop_encrypt
return
; ***************** INIT_DECRYPTION_KEY ***************************
; This procedure creates the initial deciphering key from the initial
; cyphering key by multiple application of enc_key_schedule
; Inputs: The plain_text in block[]
; The cipher_key in key[]
; Outups: The ciphered text in block
; The rounded (decipher) key in key[]
; OBS: This implementation follows as possible the original
; structure and function names used by the reference
; implementation of AES
; *****************************************************************
init_decryption_key:
movlw 0x01
movwf rcon
movlw 0xA
movwf round_counter
loop_init_decryption_key:
call enc_key_schedule
decfsz round_counter,f
goto loop_init_decryption_key
return
;0E DD 33 D3 C6 21 E5 46 45 5B D8 BA 14 18 BE C8
ORG 0x0600 ;Program Memory starting address
S_table:
addwf PCL,f
; retlw D'99' ;except S_table[0]
retlw D'124'
retlw D'119'
retlw D'123'
retlw D'242'
retlw D'107'
retlw D'111'
retlw D'197'
retlw D'48'
retlw D'1'
retlw D'103'
retlw D'43'
retlw D'254'
retlw D'215'
retlw D'171'
retlw D'118'
retlw D'202'
retlw D'130'
retlw D'201'
retlw D'125'
retlw D'250'
retlw D'89'
retlw D'71'
retlw D'240'
retlw D'173'
retlw D'212'
retlw D'162'
retlw D'175'
retlw D'156'
retlw D'164'
retlw D'114'
retlw D'192'
retlw D'183'
retlw D'253'
retlw D'147'
retlw D'38'
retlw D'54'
retlw D'63'
retlw D'247'
retlw D'204'
retlw D'52'
retlw D'165'
retlw D'229'
retlw D'241'
retlw D'113'
retlw D'216'
retlw D'49'
retlw D'21'
retlw D'4'
retlw D'199'
retlw D'35'
retlw D'195'
retlw D'24'
retlw D'150'
retlw D'5'
retlw D'154'
retlw D'7'
retlw D'18'
retlw D'128'
retlw D'226'
retlw D'235'
retlw D'39'
retlw D'178'
retlw D'117'
retlw D'9'
retlw D'131'
retlw D'44'
retlw D'26'
retlw D'27'
retlw D'110'
retlw D'90'
retlw D'160'
retlw D'82'
retlw D'59'
retlw D'214'
retlw D'179'
retlw D'41'
retlw D'227'
retlw D'47'
retlw D'132'
retlw D'83'
retlw D'209'
retlw D'0'
retlw D'237'
retlw D'32'
retlw D'252'
retlw D'177'
retlw D'91'
retlw D'106'
retlw D'203'
retlw D'190'
retlw D'57'
retlw D'74'
retlw D'76'
retlw D'88'
retlw D'207'
retlw D'208'
retlw D'239'
retlw D'170'
retlw D'251'
retlw D'67'
retlw D'77'
retlw D'51'
retlw D'133'
retlw D'69'
retlw D'249'
retlw D'2'
retlw D'127'
retlw D'80'
retlw D'60'
retlw D'159'
retlw D'168'
retlw D'81'
retlw D'163'
retlw D'64'
retlw D'143'
retlw D'146'
retlw D'157'
retlw D'56'
retlw D'245'
retlw D'188'
retlw D'182'
retlw D'218'
retlw D'33'
retlw D'16'
retlw D'255'
retlw D'243'
retlw D'210'
retlw D'205'
retlw D'12'
retlw D'19'
retlw D'236'
retlw D'95'
retlw D'151'
retlw D'68'
retlw D'23'
retlw D'196'
retlw D'167'
retlw D'126'
retlw D'61'
retlw D'100'
retlw D'93'
retlw D'25'
retlw D'115'
retlw D'96'
retlw D'129'
retlw D'79'
retlw D'220'
retlw D'34'
retlw D'42'
retlw D'144'
retlw D'136'
retlw D'70'
retlw D'238'
retlw D'184'
retlw D'20'
retlw D'222'
retlw D'94'
retlw D'11'
retlw D'219'
retlw D'224'
retlw D'50'
retlw D'58'
retlw D'10'
retlw D'73'
retlw D'6'
retlw D'36'
retlw D'92'
retlw D'194'
retlw D'211'
retlw D'172'
retlw D'98'
retlw D'145'
retlw D'149'
retlw D'228'
retlw D'121'
retlw D'231'
retlw D'200'
retlw D'55'
retlw D'109'
retlw D'141'
retlw D'213'
retlw D'78'
retlw D'169'
retlw D'108'
retlw D'86'
retlw D'244'
retlw D'234'
retlw D'101'
retlw D'122'
retlw D'174'
retlw D'8'
retlw D'186'
retlw D'120'
retlw D'37'
retlw D'46'
retlw D'28'
retlw D'166'
retlw D'180'
retlw D'198'
retlw D'232'
retlw D'221'
retlw D'116'
retlw D'31'
retlw D'75'
retlw D'189'
retlw D'139'
retlw D'138'
retlw D'112'
retlw D'62'
retlw D'181'
retlw D'102'
retlw D'72'
retlw D'3'
retlw D'246'
retlw D'14'
retlw D'97'
retlw D'53'
retlw D'87'
retlw D'185'
retlw D'134'
retlw D'193'
retlw D'29'
retlw D'158'
retlw D'225'
retlw D'248'
retlw D'152'
retlw D'17'
retlw D'105'
retlw D'217'
retlw D'142'
retlw D'148'
retlw D'155'
retlw D'30'
retlw D'135'
retlw D'233'
retlw D'206'
retlw D'85'
retlw D'40'
retlw D'223'
retlw D'140'
retlw D'161'
retlw D'137'
retlw D'13'
retlw D'191'
retlw D'230'
retlw D'66'
retlw D'104'
retlw D'65'
retlw D'153'
retlw D'45'
retlw D'15'
retlw D'176'
retlw D'84'
retlw D'187'
retlw D'22'
ORG 0x0700 ;Program Memory starting address
Si_table:
addwf PCL,f
; retlw D'82' ;except Si_table[0]
retlw D'9'
retlw D'106'
retlw D'213'
retlw D'48'
retlw D'54'
retlw D'165'
retlw D'56'
retlw D'191'
retlw D'64'
retlw D'163'
retlw D'158'
retlw D'129'
retlw D'243'
retlw D'215'
retlw D'251'
retlw D'124'
retlw D'227'
retlw D'57'
retlw D'130'
retlw D'155'
retlw D'47'
retlw D'255'
retlw D'135'
retlw D'52'
retlw D'142'
retlw D'67'
retlw D'68'
retlw D'196'
retlw D'222'
retlw D'233'
retlw D'203'
retlw D'84'
retlw D'123'
retlw D'148'
retlw D'50'
retlw D'166'
retlw D'194'
retlw D'35'
retlw D'61'
retlw D'238'
retlw D'76'
retlw D'149'
retlw D'11'
retlw D'66'
retlw D'250'
retlw D'195'
retlw D'78'
retlw D'8'
retlw D'46'
retlw D'161'
retlw D'102'
retlw D'40'
retlw D'217'
retlw D'36'
retlw D'178'
retlw D'118'
retlw D'91'
retlw D'162'
retlw D'73'
retlw D'109'
retlw D'139'
retlw D'209'
retlw D'37'
retlw D'114'
retlw D'248'
retlw D'246'
retlw D'100'
retlw D'134'
retlw D'104'
retlw D'152'
retlw D'22'
retlw D'212'
retlw D'164'
retlw D'92'
retlw D'204'
retlw D'93'
retlw D'101'
retlw D'182'
retlw D'146'
retlw D'108'
retlw D'112'
retlw D'72'
retlw D'80'
retlw D'253'
retlw D'237'
retlw D'185'
retlw D'218'
retlw D'94'
retlw D'21'
retlw D'70'
retlw D'87'
retlw D'167'
retlw D'141'
retlw D'157'
retlw D'132'
retlw D'144'
retlw D'216'
retlw D'171'
retlw D'0'
retlw D'140'
retlw D'188'
retlw D'211'
retlw D'10'
retlw D'247'
retlw D'228'
retlw D'88'
retlw D'5'
retlw D'184'
retlw D'179'
retlw D'69'
retlw D'6'
retlw D'208'
retlw D'44'
retlw D'30'
retlw D'143'
retlw D'202'
retlw D'63'
retlw D'15'
retlw D'2'
retlw D'193'
retlw D'175'
retlw D'189'
retlw D'3'
retlw D'1'
retlw D'19'
retlw D'138'
retlw D'107'
retlw D'58'
retlw D'145'
retlw D'17'
retlw D'65'
retlw D'79'
retlw D'103'
retlw D'220'
retlw
[size=9:57c4fb864a][color=#999