Remote Access Control


aes.c File Reference


Detailed Description

Source file for AES public and support functions.

This file contains the function implementation for the AES algorithm. Refer to the aes.h file for more details.

Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Name
Revision
4337
Date
2008-08-08 10:52:47 +0200 (fr, 08 aug 2008)

Copyright (c) 2006, Atmel Corporation All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file aes.c.

#include "aes.h"
#include "common.h"
#include "config.h"

Include dependency graph for aes.c:

Go to the source code of this file.

Defines

#define BPOLY   0x1b

Functions

static void addAndCopy (byte *buf1, byte *buf2, byte count)
static void addConstantAndSubstitute (byte *bytes, const byte *constant, byte count)
static void calcLastRoundKey (byte *scheduleBuffer)
void cipher (byte *block, byte *scheduleBuffer, const byte *key)
static void cycleLeft (byte *row)
void invCipher (byte *block, byte *scheduleBuffer)
static void invKeyExpansion (byte *scheduleBuffer, byte *roundConstant)
static void invMixColumn (byte *column)
static void invMixColumns (byte *state)
static void invShiftRows (byte *state)
static void invSubstituteAndAddConstant (byte *bytes, const byte *constant, byte count)
static void keyExpansion (byte *scheduleBuffer, byte *roundConstant)
static void mixColumn (byte *column)
static void mixColumns (byte *state)
void prepareInvCipher (byte *scheduleBuffer, const byte *key)
static void shiftRows (byte *state)
static void subBytes (byte *bytes, byte count)

Variables

const byte __flash sBox [256]
const byte __flash sBoxInv [256]


Define Documentation

#define BPOLY   0x1b

Lower 8 bits of AES polynomial (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).

Definition at line 55 of file aes.c.

Referenced by invCipher(), invKeyExpansion(), invMixColumn(), keyExpansion(), and mixColumn().


Function Documentation

static void addAndCopy ( byte buf1,
byte buf2,
byte  count 
) [static]

XOR 'count' bytes from 'buf1' and 'buf2' buffers and copy result to both buffers.

Definition at line 467 of file aes.c.

Referenced by keyExpansion().

00468 {
00469         // Copy to temporary variables for optimization.
00470         byte * tempBuf1 = buf1;
00471         byte * tempBuf2 = buf2;
00472         byte tempCount = count;
00473         byte tempValue;
00474 
00475         do {
00476                  // Add in GF(2), ie. XOR.
00477                 tempValue = *tempBuf1 ^ *tempBuf2;
00478                 *tempBuf1++ = tempValue;
00479                 *tempBuf2++ = tempValue;
00480         } while( --tempCount );
00481 }

static void addConstantAndSubstitute ( byte bytes,
const byte constant,
byte  count 
) [static]

XOR 'count' bytes from 'constant' buffer into 'bytes' and substitute using S-Box.

Definition at line 508 of file aes.c.

References sBox.

Referenced by cipher().

00509 {
00510         // Copy to temporary variables for optimization.
00511         byte * tempDestination = bytes;
00512         const byte * tempSource = constant;
00513         byte tempCount = count;
00514         byte tempValue;
00515 
00516         do {
00517                 // Add in GF(2), ie. XOR.
00518                 tempValue = *tempDestination ^ *tempSource++;
00519                 *tempDestination++ = sBox[ tempValue ];
00520         } while( --tempCount );
00521 }

static void calcLastRoundKey ( byte scheduleBuffer  )  [static]

Prepare last round key in schedule given the initial key in 'scheduleBuffer' and 'roundConstant'.

Definition at line 817 of file aes.c.

References keyExpansion(), ROUNDS, and SCHEDULE_BLOCK_REPETITIONS.

Referenced by prepareInvCipher().

00818 {
00819         byte roundConstant[ 4 ] = { 0x01, 0x00, 0x00, 0x00 };
00820 
00821 #if SCHEDULE_KEY_REPETITIONS > 1
00822         initialKeyExpansion( scheduleBuffer, roundConstant );
00823 #endif
00824 
00825         byte round;
00826         for( round = 1; round < ROUNDS+1; round += SCHEDULE_BLOCK_REPETITIONS ) {
00827                 keyExpansion( scheduleBuffer, roundConstant );
00828         }
00829 }

Here is the call graph for this function:

void cipher ( byte block,
byte scheduleBuffer,
const byte key 
)

Encrypt data block with on-the-fly calculation of key schedule in 'scheduleBuffer'.

Definition at line 833 of file aes.c.

References addConstant(), addConstantAndSubstitute(), BLOCK_SIZE, copyBytes(), KEY_SIZE, keyExpansion(), mixColumns(), ROUNDS, and shiftRows().

Referenced by calcCMAC(), and calcCMACSubkey().

00834 {
00835         byte roundConstant[4] = { 0x01, 0x00, 0x00, 0x00 };
00836 
00837         copyBytes( scheduleBuffer, key, KEY_SIZE );
00838 #if SCHEDULE_KEY_REPETITIONS > 1
00839         initialKeyExpansion( scheduleBuffer, roundConstant );
00840 #endif
00841 
00842 #if KEY_SIZE == 16
00843         byte round;
00844         for( round = 0; round < ROUNDS-1; ++round ) {
00845                 addConstantAndSubstitute( block, scheduleBuffer, BLOCK_SIZE );
00846                 shiftRows( block );
00847                 mixColumns( block );
00848 
00849                 keyExpansion( scheduleBuffer, roundConstant );
00850         }
00851 
00852         addConstantAndSubstitute( block, scheduleBuffer, BLOCK_SIZE );
00853         shiftRows( block );
00854 
00855         keyExpansion( scheduleBuffer, roundConstant );
00856         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00857 
00858 #elif KEY_SIZE == 24
00859         byte round;
00860         for( round = 0; round < ROUNDS-3; round += 3 ) {
00861                 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00862                 shiftRows( block );
00863                 mixColumns( block );
00864 
00865                 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00866                 shiftRows( block );
00867                 mixColumns( block );
00868 
00869                 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00870                 shiftRows( block );
00871                 mixColumns( block );
00872 
00873                 keyExpansion( scheduleBuffer, roundConstant );
00874         }
00875 
00876         addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00877         shiftRows( block );
00878         mixColumns( block );
00879 
00880         addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00881         shiftRows( block );
00882         mixColumns( block );
00883 
00884         addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00885         shiftRows( block );
00886 
00887         keyExpansion( scheduleBuffer, roundConstant );
00888         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00889 
00890 #elif KEY_SIZE == 32
00891         byte round;
00892         for( round = 0; round < ROUNDS-2; round += 2 ) {
00893                 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00894                 shiftRows( block );
00895                 mixColumns( block );
00896 
00897                 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00898                 shiftRows( block );
00899                 mixColumns( block );
00900 
00901                 keyExpansion( scheduleBuffer, roundConstant );
00902         }
00903 
00904         addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00905         shiftRows( block );
00906         mixColumns( block );
00907 
00908         addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00909         shiftRows( block );
00910 
00911         keyExpansion( scheduleBuffer, roundConstant );
00912         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00913 
00914 #else
00915   #error Unsupported key size.
00916 #endif
00917 }

Here is the call graph for this function:

static void cycleLeft ( byte row  )  [static]

Cycle a 4-byte array left once.

Definition at line 134 of file aes.c.

Referenced by invKeyExpansion(), and keyExpansion().

00135 {
00136         // Cycle 4 bytes in an array left once.
00137         byte temp = row[0];
00138         row[0] = row[1];
00139         row[1] = row[2];
00140         row[2] = row[3];
00141         row[3] = temp;
00142 }

void invCipher ( byte block,
byte scheduleBuffer 
)

Decrypt data block using prepared key schedule state from 'scheduleBuffer'.

Definition at line 929 of file aes.c.

References addConstant(), BLOCK_SIZE, BPOLY, invKeyExpansion(), invMixColumns(), invShiftRows(), invSubstituteAndAddConstant(), LAST_ROUND_CONSTANT, and ROUNDS.

Referenced by learnMode().

00930 {
00931         byte roundConstant[4] = { LAST_ROUND_CONSTANT, 0x00, 0x00, 0x00 };
00932 
00933 #if KEY_SIZE == 16
00934         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00935 
00936         byte round;
00937         for( round = 0; round < ROUNDS-1; ++round ) {
00938                 invKeyExpansion( scheduleBuffer, roundConstant );
00939 
00940                 invShiftRows( block );
00941                 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
00942                 invMixColumns( block );
00943         }
00944 
00945         invKeyExpansion( scheduleBuffer, roundConstant );
00946 
00947         invShiftRows( block );
00948         invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
00949 
00950 #elif KEY_SIZE == 24
00951         // Backtrace last update of round constant, since it is never
00952         // used, due to the use of two KEY_SIZEs in schedule buffer.
00953         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00954                 roundConstant[0] = 0x80;
00955         } else {
00956                 roundConstant[0] >>= 1;
00957         }
00958 
00959         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00960 
00961         byte round;
00962         for( round = 0; round < ROUNDS-3; round += 3 ) {
00963                 invKeyExpansion( scheduleBuffer, roundConstant );
00964 
00965                 invShiftRows( block );
00966                 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00967                 invMixColumns( block );
00968 
00969                 invShiftRows( block );
00970                 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00971                 invMixColumns( block );
00972 
00973                 invShiftRows( block );
00974                 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00975                 invMixColumns( block );
00976         }
00977 
00978         invKeyExpansion( scheduleBuffer, roundConstant );
00979 
00980         invShiftRows( block );
00981         invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00982         invMixColumns( block );
00983 
00984         invShiftRows( block );
00985         invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00986         invMixColumns( block );
00987 
00988         invShiftRows( block );
00989         invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00990 
00991 #elif KEY_SIZE == 32
00992         addConstant( block, scheduleBuffer, BLOCK_SIZE );
00993 
00994         byte round;
00995         for( round = 0; round < ROUNDS-2; round += 2 ) {
00996                 invKeyExpansion( scheduleBuffer, roundConstant );
00997 
00998                 invShiftRows( block );
00999                 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE, BLOCK_SIZE );
01000                 invMixColumns( block );
01001 
01002                 invShiftRows( block );
01003                 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
01004                 invMixColumns( block );
01005         }
01006 
01007         invKeyExpansion( scheduleBuffer, roundConstant );
01008 
01009         invShiftRows( block );
01010         invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE, BLOCK_SIZE );
01011         invMixColumns( block );
01012 
01013         invShiftRows( block );
01014         invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
01015 
01016 #else
01017   #error Unsupported key size.
01018 #endif
01019 }

Here is the call graph for this function:

static void invKeyExpansion ( byte scheduleBuffer,
byte roundConstant 
) [static]

Calculate previous round key from current round key in 'scheduleBuffer' and 'roundConstant'.

Definition at line 683 of file aes.c.

References addConstant(), BLOCK_SIZE, BPOLY, copyBytes(), cycleLeft(), KEY_SIZE, SCHEDULE_BUFFER_SIZE, and subBytes().

Referenced by invCipher().

00684 {
00685         byte tempWord[4];
00686 
00687 #if KEY_SIZE == 16 || KEY_SIZE == 32
00688         byte schedulePos = SCHEDULE_BUFFER_SIZE - 4;
00689         scheduleBuffer += SCHEDULE_BUFFER_SIZE - 4;
00690 
00691   #if KEY_SIZE == 32
00692         do {
00693                 // Add with previous word.
00694                 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00695 
00696                 // Move to previous word in schedule.
00697                 scheduleBuffer -= 4;
00698                 schedulePos -= 4;
00699 
00700         } while( schedulePos > BLOCK_SIZE );
00701 
00702         // Prepare substitution of previous word.
00703         copyBytes( tempWord, scheduleBuffer - 4, 4 );
00704         subBytes( tempWord, 4 );
00705 
00706         // Add substituted word to current word.
00707         addConstant( scheduleBuffer, tempWord, 4 );
00708 
00709         // Move to previous word in schedule.
00710         scheduleBuffer -= 4;
00711         schedulePos -= 4;
00712   #endif
00713 
00714         do {
00715                 // Add with previous word.
00716                 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00717 
00718                 // Move to previous word in schedule.
00719                 scheduleBuffer -= 4;
00720                 schedulePos -= 4;
00721 
00722         } while( schedulePos > 0 );
00723 
00724         // Prepare round constant for transformation that follows.
00725         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00726                 roundConstant[0] = 0x80;
00727         } else {
00728                 roundConstant[0] >>= 1;
00729         }
00730 
00731         // Prepare transformation of previous word (which is now at end of buffer).
00732         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00733         cycleLeft( tempWord );
00734         subBytes( tempWord, 4 );
00735         addConstant( tempWord, roundConstant, 4 );
00736 
00737         // Apply transformation result to current word.
00738         addConstant( scheduleBuffer, tempWord, 4 );
00739 
00740 #elif KEY_SIZE == 24
00741         // Move to end of first KEY_SIZE in schedule.
00742         byte schedulePos = (SCHEDULE_BUFFER_SIZE/2) - 4;
00743         scheduleBuffer += (SCHEDULE_BUFFER_SIZE/2) - 4;
00744 
00745         do {
00746                 // Get current word.
00747                 // Add with previous word.
00748                 // Store at position one KEY_SIZE backwards (wraps to end of buffer).
00749                 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer + KEY_SIZE, 4 );
00750 
00751                 // Move to previous word in schedule.
00752                 scheduleBuffer -= 4;
00753                 schedulePos -= 4;
00754 
00755         } while( schedulePos > 0 );
00756 
00757         // Prepare round constant for transformation that follows.
00758         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00759                 roundConstant[0] = 0x80;
00760         } else {
00761                 roundConstant[0] >>= 1;
00762         }
00763 
00764         // Prepare transformation of previous word (which is now at end of buffer).
00765         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00766         cycleLeft( tempWord );
00767         subBytes( tempWord, 4 );
00768         addConstant( tempWord, roundConstant, 4 );
00769 
00770         // Add current word to transformation result.
00771         addConstant( tempWord, scheduleBuffer, 4 );
00772         // Store at position one KEY_SIZE backwards (wraps to end of buffer).
00773         copyBytes( scheduleBuffer + KEY_SIZE, tempWord, 4 );
00774 
00775         // Move to last word in schedule.
00776         schedulePos = SCHEDULE_BUFFER_SIZE - 4;
00777         scheduleBuffer += SCHEDULE_BUFFER_SIZE - 4;
00778 
00779         do {
00780                 // Get current word.
00781                 // Add with previous word.
00782                 // Store at position one KEY_SIZE backwards.
00783                 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer - KEY_SIZE, 4 );
00784 
00785                 // Move to previous word in schedule.
00786                 scheduleBuffer -= 4;
00787                 schedulePos -= 4;
00788 
00789         } while( schedulePos > KEY_SIZE );
00790 
00791         // Prepare round constant for transformation that follows.
00792         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00793                 roundConstant[0] = 0x80;
00794         } else {
00795                 roundConstant[0] >>= 1;
00796         }
00797 
00798         // Prepare transformation of previous word.
00799         copyBytes( tempWord, scheduleBuffer - 4, 4 );
00800         cycleLeft( tempWord );
00801         subBytes( tempWord, 4 );
00802         addConstant( tempWord, roundConstant, 4 );
00803 
00804         // Add current word to transformation result.
00805         addConstant( tempWord, scheduleBuffer, 4 );
00806         // Store at position one KEY_SIZE backwards.
00807         copyBytes( scheduleBuffer - KEY_SIZE, tempWord, 4 );
00808 
00809 #else
00810   #error Unsupported key size.
00811 #endif
00812 }

Here is the call graph for this function:

static void invMixColumn ( byte column  )  [static]

Perform an AES inverse column mix operation on the 4 bytes in 'column' buffer.

Definition at line 264 of file aes.c.

References BPOLY.

Referenced by invMixColumns().

00265 {
00266         byte result0, result1, result2, result3;
00267         byte column0, column1, column2, column3;
00268         byte xor;
00269 
00270         // This generates more effective code, at least
00271         // with the IAR C compiler.
00272         column0 = column[0];
00273         column1 = column[1];
00274         column2 = column[2];
00275         column3 = column[3];
00276 
00277         // Partial sums (modular addition using XOR).
00278         result0 = column1 ^ column2 ^ column3;
00279         result1 = column0 ^ column2 ^ column3;
00280         result2 = column0 ^ column1 ^ column3;
00281         result3 = column0 ^ column1 ^ column2;
00282 
00283         // Multiply column bytes by 2 modulo BPOLY.
00284         // This operation is done the following way to ensure cycle count
00285         // independent from data contents. Take care when changing this code.
00286         xor = 0;
00287         if (column0 & 0x80) {
00288                 xor = BPOLY;
00289         }
00290         column0 <<= 1;
00291         column0  ^= xor;
00292         
00293         xor = 0;
00294         if (column1 & 0x80) {
00295                 xor = BPOLY;
00296         }
00297         column1 <<= 1;
00298         column1  ^= xor;
00299         
00300         xor = 0;
00301         if (column2 & 0x80) {
00302                 xor = BPOLY;
00303         }
00304         column2 <<= 1;
00305         column2  ^= xor;
00306         
00307         xor = 0;
00308         if (column3 & 0x80) {
00309                 xor = BPOLY;
00310         }
00311         column3 <<= 1;
00312         column3  ^= xor;
00313 
00314         // More partial sums.
00315         result0 ^= column0 ^ column1;
00316         result1 ^= column1 ^ column2;
00317         result2 ^= column2 ^ column3;
00318         result3 ^= column0 ^ column3;
00319 
00320         // Multiply column bytes by 2 modulo BPOLY.
00321         // This operation is done the following way to ensure cycle count
00322         // independent from data contents. Take care when changing this code.
00323         xor = 0;
00324         if (column0 & 0x80) {
00325                 xor = BPOLY;
00326         }
00327         column0 <<= 1;
00328         column0  ^= xor;
00329         
00330         xor = 0;
00331         if (column1 & 0x80) {
00332                 xor = BPOLY;
00333         }
00334         column1 <<= 1;
00335         column1  ^= xor;
00336         
00337         xor = 0;
00338         if (column2 & 0x80) {
00339                 xor = BPOLY;
00340         }
00341         column2 <<= 1;
00342         column2  ^= xor;
00343         
00344         xor = 0;
00345         if (column3 & 0x80) {
00346                 xor = BPOLY;
00347         }
00348         column3 <<= 1;
00349         column3  ^= xor;
00350 
00351         // More partial sums.
00352         result0 ^= column0 ^ column2;
00353         result1 ^= column1 ^ column3;
00354         result2 ^= column0 ^ column2;
00355         result3 ^= column1 ^ column3;
00356 
00357         // Multiply column bytes by 2 modulo BPOLY.
00358         // This operation is done the following way to ensure cycle count
00359         // independent from data contents. Take care when changing this code.
00360         xor = 0;
00361         if (column0 & 0x80) {
00362                 xor = BPOLY;
00363         }
00364         column0 <<= 1;
00365         column0  ^= xor;
00366         
00367         xor = 0;
00368         if (column1 & 0x80) {
00369                 xor = BPOLY;
00370         }
00371         column1 <<= 1;
00372         column1  ^= xor;
00373         
00374         xor = 0;
00375         if (column2 & 0x80) {
00376                 xor = BPOLY;
00377         }
00378         column2 <<= 1;
00379         column2  ^= xor;
00380         
00381         xor = 0;
00382         if (column3 & 0x80) {
00383                 xor = BPOLY;
00384         }
00385         column3 <<= 1;
00386         column3  ^= xor;
00387 
00388         // Final partial sum.
00389         column0 ^= column1 ^ column2 ^ column3;
00390 
00391         // Final sums stored indto original column bytes.
00392         column[0] = result0 ^ column0;
00393         column[1] = result1 ^ column0;
00394         column[2] = result2 ^ column0;
00395         column[3] = result3 ^ column0;
00396 }

static void invMixColumns ( byte state  )  [static]

Perform AES inverse column mixing for the whole AES block/state.

Definition at line 401 of file aes.c.

References invMixColumn().

Referenced by invCipher().

00402 {
00403         invMixColumn( state + 0*4 );
00404         invMixColumn( state + 1*4 );
00405         invMixColumn( state + 2*4 );
00406         invMixColumn( state + 3*4 );
00407 }

Here is the call graph for this function:

static void invShiftRows ( byte state  )  [static]

Perform AES inverse shift rows operation for the whole AES block/state.

Definition at line 412 of file aes.c.

Referenced by invCipher().

00413 {
00414         byte temp;
00415 
00416         // Note: State is arranged column by column.
00417 
00418         // Cycle second row right one time.
00419         temp = state[ 1 + 3*4 ];
00420         state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
00421         state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
00422         state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
00423         state[ 1 + 0*4 ] = temp;
00424 
00425         // Cycle third row right two times.
00426         temp = state[ 2 + 0*4 ];
00427         state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
00428         state[ 2 + 2*4 ] = temp;
00429         temp = state[ 2 + 1*4 ];
00430         state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
00431         state[ 2 + 3*4 ] = temp;
00432 
00433         // Cycle fourth row right three times, ie. left once.
00434         temp = state[ 3 + 0*4 ];
00435         state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
00436         state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
00437         state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
00438         state[ 3 + 3*4 ] = temp;
00439 }

static void invSubstituteAndAddConstant ( byte bytes,
const byte constant,
byte  count 
) [static]

Substitute 'count' bytes from 'bytes' using inverse S-Box, XOR with 'constant' and store in 'bytes'.

Definition at line 526 of file aes.c.

References sBoxInv.

Referenced by invCipher().

00527 {
00528         // Copy to temporary variables for optimization.
00529         byte * tempDestination = bytes;
00530         const byte * tempSource = constant;
00531         byte tempCount = count;
00532         byte tempValue;
00533 
00534         do {
00535                 // Add in GF(2), ie. XOR.
00536                 tempValue = *tempDestination;
00537                 *tempDestination++ = sBoxInv[ tempValue ] ^ *tempSource++;
00538         } while( --tempCount );
00539 }

static void keyExpansion ( byte scheduleBuffer,
byte roundConstant 
) [static]

Calculates next round key from current round key in 'scheduleBuffer' and 'roundConstant'.

Definition at line 544 of file aes.c.

References addAndCopy(), addConstant(), BLOCK_SIZE, BPOLY, copyBytes(), cycleLeft(), KEY_SIZE, SCHEDULE_BUFFER_SIZE, and subBytes().

Referenced by calcLastRoundKey(), and cipher().

00545 {
00546         byte tempWord[4];
00547         byte schedulePos = 0;
00548 
00549         // Get last word from previous schedule buffer.
00550         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00551 
00552         // Transform it, since we are at a KEY_SIZE boundary in the schedule.
00553         cycleLeft( tempWord );
00554         subBytes( tempWord, 4 );
00555         addConstant( tempWord, roundConstant, 4 );
00556 
00557         // Update round constant.
00558         if( roundConstant[0] & 0x80 ) {
00559                 roundConstant[0] <<= 1;
00560                 roundConstant[0] ^= BPOLY;
00561         } else {
00562                 roundConstant[0] <<= 1;
00563         }
00564 
00565 #if KEY_SIZE == 16 || KEY_SIZE == 32
00566 
00567   #if KEY_SIZE == 32
00568         do {
00569                 // Add value from one KEY_SIZE backwards, ie. in last schedule buffer.
00570                 // Store in buffer, replacing old value, which was one KEY_SIZE backwards.
00571                 addAndCopy( tempWord, scheduleBuffer, 4 );
00572 
00573                 // Move to next word in schedule buffer.
00574                 scheduleBuffer += 4;
00575                 schedulePos += 4;
00576 
00577         } while( schedulePos < BLOCK_SIZE );
00578 
00579         // Substitute previous word when at BLOCK_SIZE boundary with 256 bit keys.
00580         subBytes( tempWord, 4 );
00581   #endif
00582 
00583         do {
00584                 // Add value from one KEY_SIZE backwards, ie. in last schedule buffer.
00585                 // Store in buffer, replacing old value, which was one KEY_SIZE backwards.
00586                 addAndCopy( tempWord, scheduleBuffer, 4 );
00587 
00588                 // Move to next word in schedule buffer.
00589                 scheduleBuffer += 4;
00590                 schedulePos += 4;
00591 
00592         } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00593 
00594 #elif KEY_SIZE == 24
00595         do {
00596                 // Add value from one KEY_SIZE backwards (wraps to end of buffer).
00597                 // Store in buffer, replacing old value.
00598                 addConstantAndCopy( tempWord, scheduleBuffer + KEY_SIZE, scheduleBuffer, 4 );
00599 
00600                 // Move to next word in schedule buffer.
00601                 scheduleBuffer += 4;
00602                 schedulePos += 4;
00603 
00604         } while( schedulePos < KEY_SIZE );
00605 
00606         // Transform previous word, since we are at a KEY_SIZE boundary in the schedule.
00607         cycleLeft( tempWord );
00608         subBytes( tempWord, 4 );
00609         addConstant( tempWord, roundConstant, 4 );
00610 
00611         // Update round constant.
00612         if( roundConstant[0] & 0x80 ) {
00613                 roundConstant[0] <<= 1;
00614                 roundConstant[0] ^= BPOLY;
00615         } else {
00616                 roundConstant[0] <<= 1;
00617         }
00618 
00619         do {
00620                 // Add value from one KEY_SIZE backwards.
00621                 // Store in buffer, replacing old value.
00622                 addConstantAndCopy( tempWord, scheduleBuffer - KEY_SIZE, scheduleBuffer, 4 );
00623 
00624                 // Move to next word in schedule buffer.
00625                 scheduleBuffer += 4;
00626                 schedulePos += 4;
00627 
00628         } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00629 
00630 #else
00631   #error Unsupported key size.
00632 #endif
00633 }

Here is the call graph for this function:

static void mixColumn ( byte column  )  [static]

Perform an AES column mix operation on the 4 bytes in 'column' buffer.

Definition at line 147 of file aes.c.

References BPOLY.

Referenced by mixColumns().

00148 {
00149         byte result0, result1, result2, result3;
00150         byte column0, column1, column2, column3;
00151 
00152         // This generates more effective code, at least
00153         // with the IAR C compiler.
00154         column0 = column[0];
00155         column1 = column[1];
00156         column2 = column[2];
00157         column3 = column[3];
00158 
00159         // Partial sums (modular addition using XOR).
00160         result0 = column1 ^ column2 ^ column3;
00161         result1 = column0 ^ column2 ^ column3;
00162         result2 = column0 ^ column1 ^ column3;
00163         result3 = column0 ^ column1 ^ column2;
00164 
00165         // Multiply column bytes by 2 modulo BPOLY.
00166         // This operation is done the following way to ensure cycle count
00167         // independent from data contents. Take care when changing this code.
00168         xor = 0;
00169         if (column0 & 0x80) {
00170                 xor = BPOLY;
00171         }
00172         column0 <<= 1;
00173         column0  ^= xor;
00174         
00175         xor = 0;
00176         if (column1 & 0x80) {
00177                 xor = BPOLY;
00178         }
00179         column1 <<= 1;
00180         column1  ^= xor;
00181         
00182         xor = 0;
00183         if (column2 & 0x80) {
00184                 xor = BPOLY;
00185         }
00186         column2 <<= 1;
00187         column2  ^= xor;
00188         
00189         xor = 0;
00190         if (column3 & 0x80) {
00191                 xor = BPOLY;
00192         }
00193         column3 <<= 1;
00194         column3  ^= xor;
00195 
00196         // Final sums stored into original column bytes.
00197         column[0] = result0 ^ column0 ^ column1;
00198         column[1] = result1 ^ column1 ^ column2;
00199         column[2] = result2 ^ column2 ^ column3;
00200         column[3] = result3 ^ column0 ^ column3;
00201 }

static void mixColumns ( byte state  )  [static]

Perform AES column mixing for the whole AES block/state.

Definition at line 206 of file aes.c.

References mixColumn().

Referenced by cipher().

00207 {
00208         mixColumn( state + 0*4 );
00209         mixColumn( state + 1*4 );
00210         mixColumn( state + 2*4 );
00211         mixColumn( state + 3*4 );
00212 }

Here is the call graph for this function:

void prepareInvCipher ( byte scheduleBuffer,
const byte key 
)

Calculate starting point for key schedule to be used for decryption.

Definition at line 921 of file aes.c.

References calcLastRoundKey(), copyBytes(), and KEY_SIZE.

Referenced by learnMode().

00922 {
00923         copyBytes( scheduleBuffer, key, KEY_SIZE );
00924         calcLastRoundKey( scheduleBuffer );
00925 }

Here is the call graph for this function:

static void shiftRows ( byte state  )  [static]

Perform AES shift-rows operation for the whole AES block/state.

Definition at line 232 of file aes.c.

Referenced by cipher().

00233 {
00234         byte temp;
00235 
00236         // Note: State is arranged column by column.
00237 
00238         // Cycle second row left one time.
00239         temp = state[ 1 + 0*4 ];
00240         state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
00241         state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
00242         state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
00243         state[ 1 + 3*4 ] = temp;
00244 
00245         // Cycle third row left two times.
00246         temp = state[ 2 + 0*4 ];
00247         state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
00248         state[ 2 + 2*4 ] = temp;
00249         temp = state[ 2 + 1*4 ];
00250         state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
00251         state[ 2 + 3*4 ] = temp;
00252 
00253         // Cycle fourth row left three times, ie. right once.
00254         temp = state[ 3 + 3*4 ];
00255         state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
00256         state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
00257         state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
00258         state[ 3 + 0*4 ] = temp;
00259 }

static void subBytes ( byte bytes,
byte  count 
) [static]

Substitute 'count' bytes in the 'bytes' buffer in SRAM using the S-Box.

Definition at line 217 of file aes.c.

References sBox.

Referenced by invKeyExpansion(), and keyExpansion().

00218 {
00219         // Copy to temporary variables for optimization.
00220         byte * tempPtr = bytes;
00221         byte tempCount = count;
00222 
00223         do {
00224                 *tempPtr = sBox[ *tempPtr ]; // Substitute every byte in state.
00225                 ++tempPtr;
00226         } while( --tempCount );
00227 }


Variable Documentation

const byte __flash sBox[256]

S-Box lookup table.

Definition at line 60 of file aes.c.

Referenced by addConstantAndSubstitute(), and subBytes().

const byte __flash sBoxInv[256]

Inverse S-Box lookup table.

Definition at line 96 of file aes.c.

Referenced by invSubstituteAndAddConstant().

@DOC_TITLE@
Generated on Fri Aug 8 11:03:51 2008 for AVR411 Secure Rolling Code Algorithm (Receiver) by doxygen 1.4.7