Xmega Application Note


AES_driver.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00067 #include "AES_driver.h"
00068 
00069 
00081 void AES_interrupt_driver_init(AES_interrupt_driver_t * interrupt_driver,
00082                                uint8_t * input_ptr,
00083                                uint8_t * output_ptr,
00084                                uint8_t * AES_key,
00085                                uint8_t * AES_CBC_init,
00086                                uint8_t block_count,
00087                                bool decrypt)
00088 {
00089         /* Initialize interrupt driver struct. */
00090         interrupt_driver->block_count = block_count;
00091         interrupt_driver->blocks_left = block_count;
00092         interrupt_driver->output_ptr = output_ptr;
00093         interrupt_driver->input_ptr = input_ptr;
00094         interrupt_driver->key_ptr = AES_key;
00095         interrupt_driver->init_ptr = AES_CBC_init;
00096         interrupt_driver->decrypt = decrypt;
00097 }
00098 
00099 
00100 
00112 bool AES_interrupt_driver_start(AES_interrupt_driver_t * interrupt_driver,
00113                                 AES_INTLVL_t int_lvl)
00114 {
00115         bool start_ok;
00116 
00117         /* Remove pending AES interrupts. */
00118         AES.STATUS = (AES_ERROR_bm | AES_SRIF_bm);
00119 
00120         /* Set AES to the desired interrupt level.
00121          * NOTE: If interrupt level is set to off, interrupts will never execute. */
00122         AES.INTCTRL = int_lvl;
00123 
00124         /* Put AES module in right mode. */
00125         if(interrupt_driver->decrypt){
00126                 AES.CTRL |= AES_DECRYPT_bm;
00127         }else{
00128                 AES.CTRL = AES.CTRL & (~AES_DECRYPT_bm);
00129         }
00130 
00131         /* If encryption and there are more than one block CBC is used. In CBC
00132          * encryption the first plaintext block is xored with the initialization
00133          * vector. */
00134         if((interrupt_driver->block_count > 1) && !(interrupt_driver->decrypt)){
00135 
00136                 /* Load key to AES Key memory. */
00137                 uint8_t * temp_key_ptr = interrupt_driver->key_ptr;
00138                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00139                         AES.KEY =  *(temp_key_ptr++);
00140                 }
00141 
00142                 /* Load the first plaintext block to AES State memory. */
00143                 uint8_t * temp_input_ptr = interrupt_driver->input_ptr;
00144                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00145                         AES.STATE =  *(temp_input_ptr++);
00146                 }
00147                 interrupt_driver->input_ptr = temp_input_ptr;
00148 
00149                 /* Enable Auto mode and the XOR feature. */
00150                 AES.CTRL = AES.CTRL | AES_XOR_bm | AES_AUTO_bm;
00151 
00152                 /* Load the initialization vector to the AES State memory.
00153                  * The initialization vector is xored with the plaintext block already
00154                  * loaded into the memory and the AES module is auto started. */
00155                 uint8_t * temp_init_ptr = interrupt_driver->init_ptr;
00156                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00157                         AES.STATE =  *(temp_init_ptr++);
00158                 }
00159 
00160                 /* Check if error flag is set. */
00161                 start_ok = !(AES_error_flag_check());
00162         }
00163         /* If decryption or encryption of a single block the xor feature is not
00164          * used. */
00165         else{
00166 
00167                 /* Load key to AES Key memory. */
00168                 volatile uint8_t * temp_key_ptr = interrupt_driver->key_ptr;
00169                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00170                         AES.KEY =  *(temp_key_ptr++);
00171                 }
00172 
00173                 /* Enable Auto mode. */
00174                 AES.CTRL |= AES_AUTO_bm;
00175 
00176                 /* Load the first input block to AES State memory. */
00177                 uint8_t * temp_input_ptr = interrupt_driver->input_ptr;
00178                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00179                         AES.STATE =  *(temp_input_ptr++);
00180                 }
00181 
00182                 /* Update input pointer. */
00183                 interrupt_driver->input_ptr = temp_input_ptr;
00184 
00185                 /* Check if error flag is set. */
00186                 start_ok = !(AES_error_flag_check());
00187         }
00188 
00189         return start_ok;
00190 }
00191 
00192 
00193 
00200 void AES_interrupt_handler(AES_interrupt_driver_t * interrupt_driver)
00201 {
00202         /* If encryption is done, the answer can be read out directly from the
00203          * state memory. Then the output pointer is updated. */
00204         if(!(interrupt_driver->decrypt)){
00205 
00206                 /* Store result to memory. */
00207                 uint8_t * temp_output_ptr = interrupt_driver->output_ptr;
00208                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00209                         *(temp_output_ptr++) = AES.STATE;
00210                 }
00211 
00212                 /* Update output pointer and the number of blocks left to
00213                  * encrypt/decrypt. */
00214                 interrupt_driver->output_ptr = temp_output_ptr;
00215                 interrupt_driver->blocks_left -= 1;
00216 
00217                 /* If there are more blocks to encrypt a new encryption is started. */
00218                 if(interrupt_driver->blocks_left > 0){
00219 
00220                         /* Load key to AES Key memory. */
00221                         uint8_t * temp_key_ptr = interrupt_driver->key_ptr;
00222                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00223                                 AES.KEY =  *(temp_key_ptr++);
00224                         }
00225 
00226                         /* Load the next plaintext to the AES State memory. The block is xored
00227                          * with the previous encrypted block and the AES module is auto
00228                          * started. */
00229                         uint8_t * temp_input_ptr = interrupt_driver->input_ptr;
00230                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00231                                 AES.STATE =  *(temp_input_ptr++);
00232                         }
00233 
00234                         /* Update input pointer. */
00235                         interrupt_driver->input_ptr = temp_input_ptr;
00236                 }
00237         }
00238         /* When decryption is done, the answer can only be read out directly if
00239          * there only is one block to decrypt. If there are more than one block and
00240          * CBC is used the answer must be xored with the previous cipher text or
00241          * the initialization vector to reconstruct the plaintext. */
00242         else{
00243 
00244                 /* If only one block should be decrypted the plaintext can be read out
00245                  * directly from the AES State memory. */
00246                 if(interrupt_driver->block_count == 1){
00247 
00248                         /* Store result to memory. */
00249                         uint8_t * temp_output_pointer = interrupt_driver->output_ptr;
00250                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00251                                 *(temp_output_pointer + i) = AES.STATE;
00252                         }
00253                 }
00254                 /* If there are more than one block to decrypt. */
00255                 else{
00256 
00257                         /* Disable of Auto mode and enable on the xor feature. */
00258                         AES.CTRL = (AES.CTRL & (~AES_AUTO_bm)) | AES_XOR_bm;
00259 
00260                         /* If it is the first block that is decrypted the answer must be
00261                          * xored with initialization vector to reconstruct the first
00262                          * plaintext. */
00263                         uint8_t * temp_ptr;
00264                         uint8_t temp_blocks_left = interrupt_driver->blocks_left;
00265                         if(interrupt_driver->block_count == temp_blocks_left){
00266                                 temp_ptr = interrupt_driver->init_ptr;
00267                         }
00268                         /* Else the answer must be xored with previous ciphertext value to
00269                          * reconstruct the plaintext. */
00270                         else{
00271                                 temp_ptr = interrupt_driver->input_ptr -(AES_BLOCK_LENGTH*2);
00272                         }
00273 
00274                         /* Xor the initialization vector or the previous ciphertext with
00275                          * the answer from the decryption. */
00276                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00277                                 AES.STATE =  *(temp_ptr++);
00278                         }
00279 
00280                         /* Store the result. */
00281                         uint8_t * temp_output_ptr = interrupt_driver->output_ptr;
00282                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00283                                 *(temp_output_ptr++) = AES.STATE;
00284                         }
00285 
00286                         /* Update output pointer and the number of blocks left to
00287                          * encrypt/decrypt. */
00288                         interrupt_driver->output_ptr = temp_output_ptr;
00289                         interrupt_driver->blocks_left -= 1;
00290 
00291                         /* If there are more block to decrypt a new decryption is started. */
00292                         if(interrupt_driver->blocks_left > 0){
00293 
00294                                 /* Enable the Auto mode and disable the xor feature. */
00295                                 AES.CTRL = (AES.CTRL & (~AES_XOR_bm)) | AES_AUTO_bm;
00296 
00297                                 /* Load key to AES Key memory. */
00298                                 uint8_t * temp_key_ptr = interrupt_driver->key_ptr;
00299                                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00300                                         AES.KEY =  *(temp_key_ptr++);
00301                                 }
00302 
00303                                 /* Load the next ciphertext block to the AES State memory. The
00304                                 * AES module is auto started. */
00305                                 uint8_t * temp_input_ptr = interrupt_driver->input_ptr;
00306                                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00307                                         AES.STATE =  *(temp_input_ptr++);
00308                                 }
00309 
00310                                 /* Update the input pointer. */
00311                                 interrupt_driver->input_ptr = temp_input_ptr;
00312                         }
00313                 }
00314         }
00315 }
00316 
00317 
00318 
00326 bool AES_interrupt_driver_finished(AES_interrupt_driver_t * interrupt_driver)
00327 {
00328         bool finished = (interrupt_driver->blocks_left == 0);
00329         return finished;
00330 }
00331 
00332 
00333 
00345 bool AES_encrypt(uint8_t * plaintext, uint8_t * ciphertext, uint8_t * key)
00346 {
00347         bool encrypt_ok;
00348 
00349         /* Load key into AES key memory. */
00350         uint8_t * temp_key = key;
00351         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00352                 AES.KEY =  *(temp_key++);
00353         }
00354 
00355         /* Load data into AES state memory. */
00356         uint8_t * temp_plaintext = plaintext;
00357         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00358                 AES.STATE =  *(temp_plaintext++);
00359         }
00360 
00361         /* Set AES in encryption mode and start AES. */
00362         AES.CTRL = (AES.CTRL & (~AES_DECRYPT_bm)) | AES_START_bm;
00363 
00364         do{
00365                 /* Wait until AES is finished or an error occurs. */
00366         }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00367 
00368         /* If not error. */
00369         if((AES.STATUS & AES_ERROR_bm) == 0){
00370                 /* Store the result. */
00371                 uint8_t * temp_ciphertext = ciphertext;
00372                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00373                         *(temp_ciphertext++) = AES.STATE;
00374                 }
00375                 encrypt_ok = true;
00376         }else{
00377                 encrypt_ok = false;
00378 
00379         }
00380         return encrypt_ok;
00381 }
00382 
00383 
00384 
00396 bool AES_decrypt(uint8_t * ciphertext, uint8_t * plaintext,
00397                  uint8_t * key)
00398 {
00399         bool decrypt_ok;
00400 
00401         /* Load key into AES key memory. */
00402         uint8_t * temp_key = key;
00403         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00404                 AES.KEY =  *(temp_key++);
00405         }
00406 
00407         /* Load data into AES state memory. */
00408         uint8_t * temp_ciphertext = ciphertext;
00409         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00410                 AES.STATE =  *(temp_ciphertext++);
00411         }
00412 
00413         /* Set AES in decryption mode and start the AES.*/
00414         AES.CTRL |= (AES_START_bm | AES_DECRYPT_bm);
00415 
00416         do{
00417                 /* Wait until AES is finished or an error occurs. */
00418         }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00419 
00420         /* If not error. */
00421         if((AES.STATUS & AES_ERROR_bm) == 0){
00422                 /* Store the result. */
00423                 uint8_t * temp_plaintext = plaintext;
00424                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00425                         *(temp_plaintext++) = AES.STATE;
00426                 }
00427                 decrypt_ok = true;
00428         }else{
00429                 decrypt_ok = false;
00430 
00431         }
00432         return decrypt_ok;
00433 }
00434 
00435 
00436 
00437 
00450 bool AES_lastsubkey_generate(uint8_t * key, uint8_t * last_sub_key)
00451 {
00452         bool keygen_ok;
00453         AES_software_reset();
00454 
00455         /* Load key into AES key memory. */
00456         uint8_t * temp_key = key;
00457         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00458                 AES.KEY =  *(temp_key++);
00459         }
00460 
00461         /* Load dummy data into AES state memory. */
00462         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00463                 AES.STATE =  0x00;
00464         }
00465 
00466         /* Set AES in encryption mode and start AES. */
00467         AES.CTRL = (AES.CTRL & (~AES_DECRYPT_bm)) | AES_START_bm;
00468 
00469 
00470         do{
00471                 /* Wait until AES is finished or an error occurs. */
00472         }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00473 
00474         /* If not error. */
00475         if((AES.STATUS & AES_ERROR_bm) == 0){
00476                 /* Store the last subkey. */
00477                 uint8_t * temp_last_sub_key = last_sub_key;
00478                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00479                         *(temp_last_sub_key++) = AES.KEY;
00480                 }
00481                 AES.STATUS = AES_SRIF_bm;
00482                 keygen_ok = true;
00483         }else{
00484                 AES.STATUS = AES_ERROR_bm;
00485                 keygen_ok = false;
00486 
00487         }
00488         return keygen_ok;
00489 }
00490 
00491 
00492 
00507 bool AES_CBC_encrypt(uint8_t * plaintext, uint8_t * ciphertext,
00508                      uint8_t * key, uint8_t * init, uint16_t block_count)
00509 {
00510         bool CBC_ok = true;
00511 
00512         /* The first encryption uses the initialization vector. */
00513         uint8_t * temp_init = init;
00514         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00515                 AES.STATE =  *(temp_init++);
00516         }
00517 
00518         /* Set AES in encryption mode and enables the XOR feature and the AUTO start
00519          * mode. */
00520         AES.CTRL = (AES.CTRL & (~AES_DECRYPT_bm))| AES_XOR_bm |AES_AUTO_bm;
00521 
00522         /* Temporary values used to reduce memory access. */
00523         uint8_t * temp_plaintext = plaintext;
00524         uint8_t * temp_ciphertext = ciphertext;
00525 
00526         for(uint8_t blocks_left = block_count; blocks_left > 0; blocks_left--){
00527 
00528                 /* Load key into AES key memory. */
00529                 uint8_t * temp_key = key;
00530                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00531                         AES.KEY =  *(temp_key++);
00532                 }
00533 
00534                 /* Load plaintext into AES state memory. Auto starts. */
00535                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00536                         AES.STATE =  *(temp_plaintext++);
00537                 }
00538 
00539 
00540                 do{
00541                         /* Wait until AES is finished or an error occurs. */
00542                 }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00543 
00544                 /* If not error. */
00545                 if((AES.STATUS & AES_ERROR_bm) == 0){
00546 
00547                         /* Store result. */
00548                         uint8_t * temp = temp_ciphertext;
00549                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00550                                 *(temp++) = AES.STATE;
00551                         }
00552                         temp_ciphertext = temp;
00553                 }else{
00554                         CBC_ok = false;
00555                 }
00556         }
00557 
00558         /* Turn off auto mode and xor feature. */
00559         AES.CTRL = (AES.CTRL & ~( AES_XOR_bm |AES_AUTO_bm));
00560 
00561         return CBC_ok;
00562 }
00563 
00564 
00565 
00580 bool AES_CBC_decrypt(uint8_t * ciphertext, uint8_t * plaintext,
00581                      uint8_t * key, uint8_t * init, uint16_t block_count)
00582 {
00583         bool CBC_ok = true;
00584 
00585         /* Temporary values used to reduce memory access. */
00586         uint8_t * temp_plaintext = plaintext;
00587         uint8_t * temp_ciphertext = ciphertext;
00588 
00589         for(uint8_t blocks_left = block_count; blocks_left > 0; blocks_left--){
00590 
00591                 /* Load key into AES key memory. */
00592                 uint8_t * temp_key = key;
00593                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00594                         AES.KEY =  *(temp_key++);
00595                 }
00596 
00597                 /* Load ciphertext into AES state memory. */
00598                 uint8_t * temp = temp_ciphertext;
00599                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00600                         AES.STATE =  *(temp++);
00601                 }
00602 
00603                 temp_ciphertext = temp;
00604 
00605                 /* Set AES in decryption mode and enable xor feature and start the AES. */
00606                 AES.CTRL |= (AES_DECRYPT_bm | AES_XOR_bm | AES_START_bm);
00607 
00608                 do{
00609                         /* Wait until AES is finished or an error occurs. */
00610                 }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00611 
00612                                 /* If not error. */
00613                 if((AES.STATUS & AES_ERROR_bm) == 0){
00614 
00615                         /* The first block is xored with the initialization vector. */
00616                         if(blocks_left == block_count){
00617                                 /* Load into AES state memory. */
00618                                 uint8_t * temp_init = init;
00619                                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00620                                         AES.STATE =  *(temp_init++);
00621                                 }
00622                         }
00623                         /* The other blocks is xored with the previous ciphertext block. */
00624                         else{
00625                                 /* Load into AES state memory. */
00626                                 uint8_t * last_ciphertext = temp_ciphertext - (AES_BLOCK_LENGTH*2);
00627                                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00628                                         AES.STATE =  *(last_ciphertext++);
00629                                 }
00630                         }
00631 
00632                         /* Disable XOR feature before next round. */
00633                         AES.CTRL = AES.CTRL & (~AES_XOR_bm);
00634 
00635                         /* Store the result. */
00636                         uint8_t * temp = temp_plaintext;
00637                         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00638                                 *(temp++) = AES.STATE;
00639                         }
00640                         temp_plaintext = temp;
00641                 }else{
00642                         CBC_ok = false;
00643                 }
00644 
00645         }
00646         return CBC_ok;
00647 }
00648 
00649 
00650 
00655 void AES_interruptlevel_set(AES_INTLVL_t int_lvl)
00656 {
00657         AES.INTCTRL = int_lvl;
00658 }
00659 
00660 
00661 
00662 
00678 bool AES_encrypt_backtoback(uint8_t * plaintext, uint8_t * ciphertext)
00679 {
00680         bool encrypt_ok;
00681 
00682         /* Load data into AES state memory. */
00683         uint8_t * temp_plaintext = plaintext;
00684         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00685                 AES.STATE =  *(temp_plaintext++);
00686         }
00687 
00688         /* Set AES in encryption mode and start AES. */
00689         AES.CTRL = (AES.CTRL & (~AES_DECRYPT_bm)) | AES_START_bm;
00690 
00691 
00692         do{
00693                 /* Wait until AES is finished or an error occurs. */
00694         }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00695 
00696         /* If not error. */
00697         if((AES.STATUS & AES_ERROR_bm) == 0){
00698                 /* Store the result. */
00699                 uint8_t * temp_ciphertext = ciphertext;
00700                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00701                         *(temp_ciphertext++) = AES.STATE;
00702                 }
00703                 encrypt_ok = true;
00704         }else{
00705                 encrypt_ok = false;
00706 
00707         }
00708         return encrypt_ok;
00709 }
00710 
00711 
00712 
00728 bool AES_decrypt_backtoback(uint8_t * ciphertext, uint8_t * plaintext)
00729 {
00730         bool decrypt_ok;
00731 
00732         /* Load data into AES state memory. */
00733         uint8_t * temp_ciphertext = ciphertext;
00734         for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00735                 AES.STATE =  *(temp_ciphertext++);
00736         }
00737 
00738         /* Set AES in decryption mode and start the AES.*/
00739         AES.CTRL |= (AES_START_bm | AES_DECRYPT_bm);
00740 
00741 
00742         do{
00743                 /* Wait until AES is finished or an error occurs. */
00744         }while((AES.STATUS & (AES_SRIF_bm|AES_ERROR_bm) ) == 0);
00745 
00746         /* If not error. */
00747         if((AES.STATUS & AES_ERROR_bm) == 0){
00748                 /* Store the result. */
00749                 uint8_t * temp_plaintext = plaintext;
00750                 for(uint8_t i = 0; i < AES_BLOCK_LENGTH; i++){
00751                         *(temp_plaintext++) = AES.STATE;
00752                 }
00753                 decrypt_ok = true;
00754         }else{
00755                 decrypt_ok = false;
00756 
00757         }
00758         return decrypt_ok;
00759 }
@DOC_TITLE@
Generated on Wed Apr 23 08:53:40 2008 for AVR1318 Using the XMEGA built in AES accelerator by doxygen 1.5.5