00001
00048 #include "common.h"
00049 #include "config.h"
00050 #include "aes.h"
00051 #include "cmac.h"
00052 #include "memory.h"
00053 #include "comms.h"
00054 #include "crc.h"
00055
00056
00057
00059 #pragma vector = PCINT0_vect
00060 static __interrupt void pinChangeHandler(void)
00061 {
00062 COMMAND_CODE_TYPE lastButtonState;
00063 COMMAND_CODE_TYPE newButtonState;
00064 unsigned char equalCount = 0;
00065
00066 lastButtonState = PINB & BUTTON_MASK;
00067 do {
00068 __delay_cycles( 8000 );
00069 newButtonState = PINB & BUTTON_MASK;
00070 if( newButtonState == lastButtonState ) {
00071 ++equalCount;
00072 } else {
00073 equalCount = 0;
00074 lastButtonState = newButtonState;
00075 }
00076 } while( equalCount < 10 );
00077 }
00078
00079
00080
00081 #ifndef NOWDT
00083 #pragma vector = WDT_vect
00084 __interrupt void watchdogInterrupt(void)
00085 {
00086
00087 }
00088 #endif
00089
00090
00091
00093 COMMAND_CODE_TYPE sleepAndGetCommand(void)
00094 {
00095 COMMAND_CODE_TYPE buttonState;
00096
00097
00098 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0);
00099
00100
00101 __delay_cycles( 100 );
00102 GIFR |= (1<<PCIF);
00103 GIMSK |= (1<<PCIE);
00104
00105 do {
00106 #ifndef NOWDT
00107
00108 if( !(WDTCR & (1<<WDIE)) ) {
00109 __watchdog_reset();
00110 WDTCR |= (1<<WDIE);
00111 }
00112 #endif
00113 __sleep();
00114
00115
00116 buttonState = PINB & BUTTON_MASK;
00117 } while( !buttonState );
00118
00119 GIMSK &= ~(1<<PCIE);
00120
00121 return buttonState;
00122 }
00123
00124
00125
00126
00128 void errorLoop( byte blinkCount )
00129 {
00130
00131 __watchdog_reset();
00132 WDTCR = (1<<WDCE) | (1<<WDE);
00133 WDTCR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0);
00134 WDTCR |= (1<<WDTIF) | (1<<WDTIE);
00135
00136
00137 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0);
00138
00139
00140 __enable_interrupt();
00141 DDRB = (1<<PB3);
00142 PORTB = (0<<PB3);
00143 for(;;) {
00144 __sleep();
00145 __watchdog_reset();
00146 WDTCR |= (1<<WDTIE);
00147 byte blinks;
00148 for( blinks = 0; blinks < blinkCount; ++blinks ) {
00149 PORTB = (1<<PB3);
00150 __delay_cycles( (8000000/1000)*50 );
00151 PORTB = (0<<PB3);
00152 __delay_cycles( (8000000/1000)*50 );
00153 }
00154 }
00155 }
00156
00157
00158
00160 void transmitCommandMessage( COMMAND_CODE_TYPE command )
00161 {
00162 const byte preburst = 0xff;
00163 byte i;
00164
00165 createMessage( command );
00166 startTransmission( &preburst, 1 );
00167 for( i = 0; i < PREBURST_BYTES-1; ++i ) {
00168 waitForTransmission();
00169 continueTransmission( &preburst, 1 );
00170 }
00171 waitForTransmission();
00172 continueTransmission( (const byte *)
00173 &sharedBlock.messagePayload,
00174 sizeof( struct MessagePayload ) );
00175 calcCMAC( (const byte *)
00176 &sharedBlock.messagePayload.serialNo,
00177 cryptoBlock );
00178 waitForTransmission();
00179
00180
00181
00182
00183 cryptoBlock[ MAC_BYTES ] = 0x00;
00184 continueTransmission( cryptoBlock, MAC_BYTES + 1 );
00185
00186 startCounterUpdate();
00187 waitForTransmission();
00188 stopTransmission();
00189 waitForCounterUpdate();
00190 }
00191
00192
00193
00195 void transmitTeachMessage( void )
00196 {
00197 const byte preburst = 0xff;
00198 byte i;
00199
00200 calcKeySchedule( sharedKey );
00201 initCRC();
00202 startTransmission( &preburst, 1 );
00203 for( i = 0; i < PREBURST_BYTES-1; ++i ) {
00204 waitForTransmission();
00205 continueTransmission( &preburst, 1 );
00206 }
00207 waitForTransmission();
00208 continueTransmission( (const byte*)
00209 &sharedBlock.messagePayload,
00210 SERIAL_NO_BYTES + SEQ_COUNTER_BYTES + 1 );
00211 for( i = 0; i < SERIAL_NO_BYTES + SEQ_COUNTER_BYTES; ++i ) {
00212 calcCRC( ((byte *) &sharedBlock.messagePayload.serialNo)[ i ] );
00213 }
00214 copyBytesFromEEPROM( cryptoBlock,
00215 secretKey, BLOCK_SIZE );
00216 cipherLookup( cryptoBlock );
00217 waitForTransmission();
00218 continueTransmission( cryptoBlock, BLOCK_SIZE );
00219 for( i = 0; i < BLOCK_SIZE; ++i ) {
00220 calcCRC( cryptoBlock[ i ] );
00221 }
00222 #if KEY_SIZE > BLOCK_SIZE
00223 copyBytesFromEEPROM( sharedBlock.cryptoBlock,
00224 secretKey + BLOCK_SIZE,
00225 KEY_SIZE - BLOCK_SIZE );
00226 #if KEY_SIZE < (2*BLOCK_SIZE)
00227
00228 for( i = KEY_SIZE - BLOCK_SIZE; i < BLOCK_SIZE; ++i ) {
00229 sharedBlock.cryptoBlock[ i ] = 0x00;
00230 }
00231 #endif
00232 cipherLookup( sharedBlock.cryptoBlock );
00233 waitForTransmission();
00234 continueTransmission( sharedBlock.cryptoBlock,
00235 BLOCK_SIZE );
00236 for( i = 0; i < BLOCK_SIZE; ++i ) {
00237 calcCRC( sharedBlock.cryptoBlock[ i ] );
00238 }
00239 #endif
00240
00241 calcCRC( 0x00 );
00242 calcCRC( 0x00 );
00243 waitForTransmission();
00244 continueTransmission( CRCReg, 3 );
00245 calcKeySchedule( secretKey );
00246 initializeMessage();
00247 waitForTransmission();
00248 stopTransmission();
00249 }
00250
00251
00252
00254 void handleResetFlags( void )
00255 {
00256 #ifndef NOWDT
00257 static __no_init byte __eeprom watchdogResetCount;
00258 if( watchdogResetCount == 0xff ) {
00259 watchdogResetCount = 0x00;
00260 }
00261 #endif
00262
00263
00264 byte resetFlags = MCUSR;
00265 MCUSR = 0x00;
00266
00267
00268 if( resetFlags & ((1<<PORF)|(1<<EXTRF)) ) {
00269 #ifndef NOWDT
00270 watchdogResetCount = 0;
00271 #endif
00272 }
00273 #ifndef NOWDT
00274 if( resetFlags & (1<<WDRF) ) {
00275 if( watchdogResetCount >= MAX_WATCHDOG_RESETS ) {
00276 errorLoop( 2 );
00277 } else {
00278 ++watchdogResetCount;
00279 }
00280 }
00281 #endif
00282 #ifndef NOBOD
00283 if( resetFlags & (1<<BORF) ) {
00284 errorLoop( 1 );
00285 }
00286 #endif
00287 }
00288
00289
00290
00292 void setupPeripherals( void )
00293 {
00294 #ifndef NOWDT
00295
00296 __watchdog_reset();
00297 WDTCR = (1<<WDCE) | (1<<WDE);
00298 WDTCR = (1<<WDCE) | (1<<WDE) | (1<<WDP3) | (1<<WDP0);
00299 WDTCR |= (1<<WDIF) | (1<<WDIE);
00300 #endif
00301
00302
00303 PCMSK = BUTTON_MASK;
00304
00305
00306 PORTB = (0<<PB0) |
00307 (0<<PB1) |
00308 (0<<PB2) |
00309 (0<<PB3) |
00310 (0<<PB4) |
00311 (0<<PB5);
00312 DDRB |= (1<<PB4);
00313
00314
00315 ACSR |= (1<<ACD);
00316 PRR = (1<<PRTIM1) | (1<<PRADC);
00317
00318
00319 MCUCR = (1<<SE) | (1<<SM1) | (0<<SM0);
00320 }
00321
00322
00323
00324 void main(void)
00325 {
00326 handleResetFlags();
00327 setupPeripherals();
00328 initializeMessage();
00329 calcKeySchedule( secretKey );
00330 calcCMACSubkey( cryptoBlock );
00331 __enable_interrupt();
00332
00333 for(;;) {
00334
00335 PORTB &= ~(1<<PB4);
00336 DDRB &= ~(1<<PB1);
00337
00338 COMMAND_CODE_TYPE command = sleepAndGetCommand();
00339
00340 PORTB |= (1<<PB4);
00341 DDRB |= (1<<PB1);
00342
00343
00344 __delay_cycles( 8000000 / 1000 * 5 );
00345
00346 if( command != TEACH_COMMAND ) {
00347 transmitCommandMessage( command );
00348 } else {
00349 transmitTeachMessage();
00350 }
00351 }
00352 }
00353