I have wrote two versions of AES (Rijndael) cipher code for 2 kind of microcontrollers, which are PIC16F84 and PIC16F877. Those microcontroller were able to run AES code well, but something is bothering me. I felt dissatisfied with Galois Field multiplication routine which run a bit slow due to instruction type limitation. PIC16F84 and PIC16F877 were not able to to directly implement “shift without carry”. These microcontrollers keep entering carry bit to bit 0 while doing shift left operation, and some times i feel a bit upset because of this.
To start writing this post, first i spent my time to learn PIC18F4550 instruction set and its architecture. I also spent my time to learn how lookup table was done on PIC18F4550 and also the sense of using PIC18F4550. Hmmm, now lets get ourself dirty
.
Yeah, after sitting for 4 hours. I am finally able to port my Rijndael (AES) code from PIC16F877 to PIC18F4550 with major modifications on lookup table and GF(28) routine. Horray!!!
. This new implementation gave me better improvement on decrypting routine and small improvement on encrypting routine. Nice progress, i love my new code
. It works and also fast, that was what i looking for.
My AES (Rijndael) cipher implementation on PIC18F4550 is basically divided into six versions. The characteristic of each version are listed below.
- Version 1.x is intended for unbuffered AES 128-bit
- Version 2.x is intended for unbuffered AES 192-bit (not available yet)
- Version 3.x is intended for unbuffered AES 256-bit
- Version 4.x is intended for buffered AES 128-bit
- Version 5.x is intended for buffered AES 192-bit
- Version 6.x is intended for buffered AES 256-bit
The term buffered means that all subkeys are buffered, so that the program only need to generate subkeys once all use it all the time until the new subkey are generated. By doing this, we can speed up the code by excluding key scheduling routine.
In the other side, the implementation which has no buffered (unbuffered) will perform key scheduling to generate subkey on each iteration. That was the reason why unbuffered implementation is slower than buffered implementation. But note that buffered implementation require more memory to store its subkey. If you have lots of free memory, I suggest you to use the buffered one.
See two Screenshots below, i took those picture from MPLAB v8.0, the tools where i developed this code. Nice software and Its absolutely free!. Checkout microchip website for more updates.
Plain Text

Cipher Text

Check out also materials related to this post below. If you need AES (Rijndael) implementations on PIC16F84 and PIC16F877. Please check out these links: AES (Rijndael) PIC16F84 and AES (Rijndael) PIC16F877.
RELATED STUFF
Download:
Source Code AES 128-bit unbuffered | v1.0 | v1.1 | v1.2
Source Code AES 256-bit unbuffered | v3.0 | v3.1
Source Code AES 128-bit buffered | v4.0 | v4.1 | v4.2 | v4.3 | v4.4
Source Code AES 192-bit buffered | v5.0 | v5.1 | v5.2
Source Code AES 256-bit buffered | v6.0 | v6.1 | v6.2
PIC18F4550 Datasheet
MPLAB v8.0
References:
Advanced Encryption Standard
Joan Daemen
Vincent Rijmen
Simulator:
AES(Rijndael Simulator)
Official Webiste:
- http://www.microchip.com




Hello, Thnaks alot for proving the asm codes for implementation of AES on PIC18f4550. Presently this code runs in MPLAN using C18 compiler under simulation mode. when I am trying to debug, I am not able to put a break point anywhere in the code. I am trying to modify the user key and plain text. Can u please help?
Comment by Bappaditya Mandal — 3 September 2008 @ 10:09 am
Hello, Thnaks alot for proving the asm codes for implementation of AES on PIC18f4550. Presently this code runs in MPLAB using C18 compiler under simulation mode. when I am trying to debug, I am not able to put a break point anywhere in the code. I am trying to modify the user key and plain text. Can u please help?
Comment by Bappaditya Mandal — 3 September 2008 @ 10:11 am
if i want to change the key, how to reinitialize the “subkey buffer”?…..which part of the code has that?. Thanks….wud be grateful if anyone answers this.
Comment by Bappaditya Mandal — 3 September 2008 @ 11:29 am
Hi, nice to hear your voice
To change key, you just simply initialize registers s0 to s15 or up to s23 or s31 if you use higher version of aes.
there are two type of implementation, which are buffered and unbuffered. for better result i suggest you to use the buffered one (using PIC18F4550).
In buffered version, you simply call “ksch” function to reinitialize key buffer. the function that updates key buffer is named “ksch”.
For simulation. I did not use MPLAB C18, i used MPLABSIM. i dont know how to use MPLAB C18, so i can not answer your quistion about “break point” problem.
Comment by edipermadi — 3 September 2008 @ 12:34 pm
Thanks a lot for your reply. I am using your Source Code AES 128-bit buffered – v4.3. Lets say my
key is: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
data text is: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff.
In your program where do I reinitialize this key and initialize data. Also, how do I check the cipher text (encrypted text)?, it should be: 69 c4 e0 d8 6a 7b 04 30 d8 cd b7 80 70 b4 c5 5a.
Please assume that I am not so familiar with assembly language programming.
If you just explain the working of encryption part, I can figure out the decryption part. Thanks a lot.
Comment by Bappaditya Mandal — 3 September 2008 @ 1:53 pm
Yes, you were right. encrypting 00112233445566778899aabbccddeeff with 000102030405060708090a0b0c 0d 0e 0f will result 69c4e0d86a7b0430d8cdb78070b4c55a. I tested it on my AES simulator http://jsnerd.googlepages.com/index01a.htm
you can initialize data and key before invoking encrypting routine. Once you initialize subkey, you can reuse it as many as poosible till you choose new cipher key.
If that the case, i’ll give you an example. use this piece to replace “Encrypting Routine” below org 0×00 up to decr routine.
;===============================================================================
; Program Main Entrance
;===============================================================================
org 0×00
;===============================================================================
; Test Vector
;===============================================================================
test ; key initialization
movlf k0,0×00
movlf k1,0×01
movlf k2,0×02
movlf k3,0×03
movlf k4,0×04
movlf k5,0×05
movlf k6,0×06
movlf k7,0×07
movlf k8,0×08
movlf k9,0×09
movlf k10,0×0a
movlf k11,0×0b
movlf k12,0×0c
movlf k13,0×0d
movlf k14,0×0e
movlf k15,0×0f
; plain text initialization
; now s0:s15 contain plain text
movlf s0,0×00
movlf s1,0×11
movlf s2,0×22
movlf s3,0×33
movlf s4,0×44
movlf s5,0×55
movlf s6,0×66
movlf s7,0×77
movlf s8,0×88
movlf s9,0×99
movlf s10,0xaa
movlf s11,0xbb
movlf s12,0xcc
movlf s13,0xdd
movlf s14,0xee
movlf s15,0xff
;initialize subkey buffer
call ksch
; encrypt plain text
; after this, s0:s15 contain cipher text
call encr
nop
; decrypt plain text
; after this, s0:s15 contain plain text again
call decr
goto $
;===============================================================================
; Encrypting Routine
;===============================================================================
init call ksch
nop
encr clrf fsr0l
movlf fsr0h,0×01
clrf tblptru
movlf tblptrh, HIGH(tsbox)
movlf lcnt,0×09
encra call subrow
call mixcol
decfsz lcnt,f
bra encra
call subrow
call addrnde
return ; encryption ends here
decr movlf lcnt,0×09
movlf fsr0l,0xaf
movlf fsr0h,0×01
call addrndd
call isubrow
decra call addrndd
call imixcol
call isubrow
decfsz lcnt,f
bra decra
return ; decryption ends here
Comment by edipermadi — 3 September 2008 @ 4:02 pm
Thanks for your valuable guidance.
I have created the test vector as you have suggested in the existing code.
I initialize the key using:
;initialize subkey buffer
call ksch
then call the encryption function:
; encrypt plain text
; after this, s0:s15 contain cipher text
call encr
nop
After this statement how do i check in MPLAB SIM, that the values of s0:s15 have reached the encrypted (cipher) text?
Thanks a lot for this immense help.
Comment by Bappaditya Mandal — 3 September 2008 @ 4:24 pm
Hi, Today i selected language toolsuit at
C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe
without modifying anything of ur code it gave the following errors. It seems the Sbox and Inverse Sbox Lookup Table cannot be loaded even in assembly language. Pls help me why I am getting this error:
Clean: Deleting intermediary and output files.
Clean: Deleted file “C:\D\Crypto\aes\aes-pic18F4550.mcs”.
Clean: Done.
Executing: “C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe” /q /p18F4550 “aes-18f4550.asm” /l”C:\D\Crypto\aes\aes-18f4550.lst” /e”C:\D\Crypto\aes\aes-18f4550.err” /o”C:\D\Crypto\aes\aes-18f4550.o”
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 940 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 941 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 959 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 977 : Operand contains unresolvable labels or is too complex
Halting build on first failure as requested.
BUILD FAILED: Thu Sep 04 11:21:35 2008
Thanks!
Comment by Bappaditya Mandal — 4 September 2008 @ 10:09 am
Hmmm..
I suggest you to remove all files and take the “.asm” one and try to start a new project.
don’t forget to confogure the processor to PIC18Fxxxx that compatible with PIC18F4550.
I’m wondering about this problem too. i coded, simulated and tried this code many times without any errors. Just make sure you set up everything properly
Comment by edipermadi — 4 September 2008 @ 12:54 pm
yes, i have started a new project now just compiling only ur code:
I think there is soem problem with ur table definition:
;===============================================================================
; Sbox and Inverse Sbox Lookup Table
;===============================================================================
org ($+0xff)&~0xff ; force page alignment
tsbox equ $
here it gives the error:
Clean: Deleting intermediary and output files.
Clean: Done.
Executing: “C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe” /q /p18F4550 “aes-18f4550.asm” /l”C:\D\Crypto\aes\aes-18f4550.lst” /e”C:\D\Crypto\aes\aes-18f4550.err” /o”C:\D\Crypto\aes\aes-18f4550.o”
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 940 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 941 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 959 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 977 : Operand contains unresolvable labels or is too complex
Halting build on first failure as requested.
BUILD FAILED: Thu Sep 04 14:21:08 2008
can u pls check the
org ($+0xff)&~0xff ; force page alignment
tsbox equ $
Thanks for your reply.
Comment by Bappaditya Mandal — 4 September 2008 @ 1:05 pm
OK, i see the problem
lets try this:
1. change “org ($+0xff)&~0xff” with “org $” -> apply to both tsbox and tisbox.
2. if you find initialization script that use “tsbox” and “tisbox”, please change it to “high(tsbox)” and high(tisbox)”
hopefully it works,
Comment by edipermadi — 4 September 2008 @ 1:13 pm
Thanks.
with “org $” it is giving the same error.
They are already defined as:
high(tsbox) and high(tisbox)
Will there be any problem with memory allocation using:
“org ($+0xff)&~0xff”
Comment by Bappaditya Mandal — 4 September 2008 @ 1:20 pm
I am only getting these four errors:
(a) org $ ; ($+0xff)&~0xff ; force page alignment
(b) tsbox equ $
(c) tisbox equ $
(d) get4 equ $
as:
Clean: Deleting intermediary and output files.
Clean: Done.
Executing: “C:\Program Files\Microchip\MPASM Suite\MPASMWIN.exe” /q /p18F4550 “aes-18f4550.asm” /l”C:\D\Crypto\aes\aes-18f4550.lst” /e”C:\D\Crypto\aes\aes-18f4550.err” /o”C:\D\Crypto\aes\aes-18f4550.o”
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 940 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 941 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 959 : Operand contains unresolvable labels or is too complex
Error[151] C:\D\CRYPTO\AES\AES-18F4550.ASM 977 : Operand contains unresolvable labels or is too complex
Halting build on first failure as requested.
BUILD FAILED: Thu Sep 04 14:44:17 2008
Rest all portions of ur code are fine.
Comment by Bappaditya Mandal — 4 September 2008 @ 1:27 pm
Now, all the above problems are solved.
When I reinitialize the key with the code that u have provided it gives an error:
Warning[206] C:\D\CRYPTO\AES9\AES-18F4550.ASM 293 : Found call to macro in column 1. (movlf)
Error[113] C:\D\CRYPTO\AES9\AES-18F4550.ASM 264 : Symbol not previously defined (×00)
Error[112] C:\D\CRYPTO\AES9\AES-18F4550.ASM 264 : Missing operator
Please refer to ur reply 6. Thanks a lot. I am not able to change the key and data.
Comment by Bappaditya Mandal — 4 September 2008 @ 4:01 pm
Hmm, let me triple check my code. Probably there is something wrong in my code. I’m using MPLAB v8.0.
I’ll post the result soon.
Sorry for the inconvinience,,
Comment by edipermadi — 4 September 2008 @ 4:05 pm
leave your email address to email:
“my nickname” on google mail.
Comment by edipermadi — 4 September 2008 @ 4:08 pm
Thanks a lot for all ur efforts.
All things are ‘atleast running’ properly as I expected.
Now there is a fundamental problem in ur code:
with example that ur have given:
; Encryption Benchmark:
; Plain Text = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
; Key = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
; Cipher Text = 66 e9 4b d4 ef 8a 2c 3b 88 4c fa 59 ca 34 2b 2e
;
; Encryption Benchmark:
; Cipher Text = 66 e9 4b d4 ef 8a 2c 3b 88 4c fa 59 ca 34 2b 2e
; Key = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
; Plain Text = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
This example works fine.
However, with mine example (comment 5) the encryption works. The decryption gives wrong result:
the decrypted data text is: 00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0.
and not:
00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff.
I will check with other examples too…
Comment by Bappaditya Mandal — 4 September 2008 @ 4:43 pm
my email id is bappadityamandal inside gmail. I have already send u an invitation and email.
Comment by Bappaditya Mandal — 4 September 2008 @ 4:49 pm
Hey, I would be really interested in seeing you implement this on a dsPIC30F chip and see how fast you could get it. The chip has a lot of the built in instructions that you do macros for and with the dsp on board you should be able to take advantage of the matrix math instructions.
BTW I liked the enigma implementation on the pic 16f.
Comment by Jason — 16 December 2008 @ 6:00 am
hmm, nice idea. i’ll consider your suggestion, porting AES implementation to dSPIC platforms. thank you for visiting my blog
Comment by edipermadi — 16 December 2008 @ 8:51 am
Hi
I have a problem with this code, because of your mapping. all datas defined for the spesial place on the ROM and RAM.
I’m using interrupts in my code, but to impliment this code is a problem.
do you have some ideas or C code?
thank you
Comment by nikos — 18 March 2009 @ 6:42 pm
@nikos:
hi nikos, the code was initially written as a stand alone program. That was the reason why i hardcoded everything in a special place. If you want to combine this code to another code, just declare lookup table in a certain position that acceptable for both side, for example at the end of memory program, or you could modify linker setting.
I have not written any C code for AES Implementation in microcontoller, but you can easily port it from AES x86 code. just follow what your micro C compiler said. here is a link of it:
http://www.martux.org/qemu_old/qemu-0.8.2-solaris__20061010×11/aes.c
OK, good luck
Comment by edipermadi — 19 March 2009 @ 9:40 am
For those with error:
Operand contains unresolvable labels or is too complex
Goto Project – Build options – MPASM/C17/C18 Suite Tab
and select GENERATE ABSOLUTE CODE
Then the asm will compile
Regards Edipermadi!!
Comment by luis — 13 May 2009 @ 2:17 pm
Hi,
You really did a lot of work on this, thank you so much for making it open source.
I’m trying to figure out the 256 bit buffered but I’m not sure I understand it.
When I manually change the text in RAM locations 10 to 1F it encrypts then decrypts. But then what is S0:S15 for? The header of the .asm file says these are “16 bytes of input”. I don’t know what input means? The input text is in RAM locations 10 to 1F, aren’t they? Then the key is in program memory locations K0 to K31? I want to implement this so a C program can de-crypt it. I’m using ccrypt, it’s an open-source command line tool. I want to change the key to all printable characters so I can compare the answers from each.
Comment by Tom — 9 September 2009 @ 7:06 am
@Tom:
well, in encrypting mode, s0:s15 is actually the input where you put the plaintext and it is also the ciphertext after the process is completed. In decrypting model, s0:s15 is the input of cipher text and it will be the plain text after decrypting process.
To monitor the process you may add some feature to print data in each steps in hexadecimal.
Comment by edipermadi — 17 September 2009 @ 10:18 am
Thanks again! I was able to simulate the same conditions using openssl in UNIX. I made a file with the test case of 16 bytes of zeros called 0s_input.bin, then ran the following command:
openssl enc -aes-256-cfb -nosalt -K 00000000000000000000000000000000000000000000000000000000000000 -iv 00000000000000000000000000000000 -in 0s_input.bin -out crypt.txt
The output of crypt.txt matched the test case you provided in the comments!
Comment by Tom — 27 September 2009 @ 4:46 am