X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fcc2420%2Freceive%2FCC2420ReceiveP.nc;h=4d9c055508a397292798b0fefba7a86af54b3c09;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=a85b62e8a2fbaa441216f1d37d363e5c498be059;hpb=85122e46c34408511ad13ef716c2b8a152c9d612;p=tinyos-2.x.git diff --git a/tos/chips/cc2420/receive/CC2420ReceiveP.nc b/tos/chips/cc2420/receive/CC2420ReceiveP.nc index a85b62e8..4d9c0555 100644 --- a/tos/chips/cc2420/receive/CC2420ReceiveP.nc +++ b/tos/chips/cc2420/receive/CC2420ReceiveP.nc @@ -33,12 +33,16 @@ * @author Jonathan Hui * @author David Moss * @author Jung Il Choi + * @author JeongGil Ko + * @author Razvan Musaloiu-E * @version $Revision$ $Date$ */ #include "IEEE802154.h" +#include "message.h" +#include "AM.h" -module CC2420ReceiveP { +module CC2420ReceiveP @safe() { provides interface Init; provides interface StdControl; @@ -58,7 +62,17 @@ module CC2420ReceiveP { uses interface CC2420Packet; uses interface CC2420PacketBody; uses interface CC2420Config; - + uses interface PacketTimeStamp; + + uses interface CC2420Strobe as SRXDEC; + uses interface CC2420Register as SECCTRL0; + uses interface CC2420Register as SECCTRL1; + uses interface CC2420Ram as KEY0; + uses interface CC2420Ram as KEY1; + uses interface CC2420Ram as RXNONCE; + uses interface CC2420Ram as RXFIFO_RAM; + uses interface CC2420Strobe as SNOP; + uses interface Leds; } @@ -68,6 +82,8 @@ implementation { S_STOPPED, S_STARTED, S_RX_LENGTH, + S_RX_DEC, + S_RX_DEC_WAIT, S_RX_FCF, S_RX_PAYLOAD, } cc2420_receive_state_t; @@ -78,15 +94,19 @@ implementation { SACK_HEADER_LENGTH = 7, }; - uint16_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ]; - + uint32_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ]; + uint8_t m_timestamp_head; uint8_t m_timestamp_size; /** Number of packets we missed because we were doing something else */ +#ifdef CC2420_HW_SECURITY + norace uint8_t m_missed_packets; +#else uint8_t m_missed_packets; - +#endif + /** TRUE if we are receiving a valid packet into the stack */ bool receivingPacket; @@ -95,21 +115,38 @@ implementation { norace uint8_t m_bytes_left; - norace message_t* m_p_rx_buf; + norace message_t* ONE_NOK m_p_rx_buf; message_t m_rx_buf; - +#ifdef CC2420_HW_SECURITY + norace cc2420_receive_state_t m_state; + norace uint8_t packetLength = 0; + norace uint8_t pos = 0; + norace uint8_t secHdrPos = 0; + uint8_t nonceValue[16] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + norace uint8_t skip; + norace uint8_t securityOn = 0; + norace uint8_t authentication = 0; + norace uint8_t micLength = 0; + uint8_t flush_flag = 0; + uint16_t startTime = 0; + + void beginDec(); + void dec(); +#else cc2420_receive_state_t m_state; - +#endif + /***************** Prototypes ****************/ void reset_state(); void beginReceive(); void receive(); void waitForNextPacket(); void flush(); - + bool passesAddressCheck(message_t * ONE msg); + task void receiveDone_task(); - + /***************** Init Commands ****************/ command error_t Init.init() { m_p_rx_buf = &m_rx_buf; @@ -122,6 +159,10 @@ implementation { reset_state(); m_state = S_STARTED; atomic receivingPacket = FALSE; + /* Note: + We use the falling edge because the FIFOP polarity is reversed. + This is done in CC2420Power.startOscillator from CC2420ControlP.nc. + */ call InterruptFIFOP.enableFallingEdge(); } return SUCCESS; @@ -142,7 +183,7 @@ implementation { * Start frame delimiter signifies the beginning/end of a packet * See the CC2420 datasheet for details. */ - async command void CC2420Receive.sfd( uint16_t time ) { + async command void CC2420Receive.sfd( uint32_t time ) { if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) { uint8_t tail = ( ( m_timestamp_head + m_timestamp_size ) % TIMESTAMP_QUEUE_SIZE ); @@ -170,17 +211,310 @@ implementation { /***************** InterruptFIFOP Events ****************/ async event void InterruptFIFOP.fired() { if ( m_state == S_STARTED ) { +#ifndef CC2420_HW_SECURITY + m_state = S_RX_LENGTH; beginReceive(); - +#else + m_state = S_RX_DEC; + atomic receivingPacket = TRUE; + beginDec(); +#endif } else { m_missed_packets++; } } + + /*****************Decryption Options*********************/ +#ifdef CC2420_HW_SECURITY + task void waitTask(){ + + if(SECURITYLOCK == 1){ + post waitTask(); + }else{ + m_state = S_RX_DEC; + beginDec(); + } + } + + void beginDec(){ + if(call SpiResource.isOwner()) { + dec(); + } else if (call SpiResource.immediateRequest() == SUCCESS) { + dec(); + } else { + call SpiResource.request(); + } + } + + norace uint8_t decLoopCount = 0; + + task void waitDecTask(){ + + cc2420_status_t status; + + call CSN.clr(); + status = call SNOP.strobe(); + call CSN.set(); + + atomic decLoopCount ++; + + if(decLoopCount > 10){ + call CSN.clr(); + atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) | + (0 << CC2420_SECCTRL0_SEC_M) | + (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) | + (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) | + (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ; + call CSN.set(); + SECURITYLOCK = 0; + call SpiResource.release(); + atomic flush_flag = 1; + beginReceive(); + }else if(status & CC2420_STATUS_ENC_BUSY){ + post waitDecTask(); + }else{ + call CSN.clr(); + atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) | + (0 << CC2420_SECCTRL0_SEC_M) | + (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) | + (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) | + (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ; + call CSN.set(); + SECURITYLOCK = 0; + call SpiResource.release(); + beginReceive(); + } + + } + + void waitDec(){ + cc2420_status_t status; + call CSN.clr(); + status = call SNOP.strobe(); + call CSN.set(); + + if(status & CC2420_STATUS_ENC_BUSY){ + atomic decLoopCount = 1; + post waitDecTask(); + }else{ + call CSN.clr(); + atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) | + (0 << CC2420_SECCTRL0_SEC_M) | + (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) | + (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) | + (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ; + call CSN.set(); + SECURITYLOCK = 0; + call SpiResource.release(); + beginReceive(); + } + } + + void dec(){ + cc2420_header_t header; + security_header_t secHdr; + uint8_t mode, key, temp, crc; + + atomic pos = (packetLength+pos)%RXFIFO_SIZE; + atomic secHdrPos = (pos+10)%RXFIFO_SIZE; + + if (pos + 3 > RXFIFO_SIZE){ + temp = RXFIFO_SIZE - pos; + call CSN.clr(); + atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp); + call CSN.set(); + call CSN.clr(); + atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, 3-temp); + call CSN.set(); + }else{ + call CSN.clr(); + atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, 3); + call CSN.set(); + } + + packetLength = header.length+1; + + if(packetLength == 6){ // ACK packet + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + + if (pos + sizeof(cc2420_header_t) > RXFIFO_SIZE){ + temp = RXFIFO_SIZE - pos; + call CSN.clr(); + atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp); + call CSN.set(); + call CSN.clr(); + atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, sizeof(cc2420_header_t)-temp); + call CSN.set(); + }else{ + call CSN.clr(); + atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, sizeof(cc2420_header_t)); + call CSN.set(); + } + + if (pos+header.length+1 > RXFIFO_SIZE){ + temp = header.length - (RXFIFO_SIZE - pos); + call CSN.clr(); + atomic call RXFIFO_RAM.read(temp,&crc, 1); + call CSN.set(); + }else{ + call CSN.clr(); + atomic call RXFIFO_RAM.read(pos+header.length,&crc, 1); + call CSN.set(); + } + + if(header.length+1 > RXFIFO_SIZE || !(crc << 7)){ + atomic flush_flag = 1; + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + if( (header.fcf & (1 << IEEE154_FCF_SECURITY_ENABLED)) && (crc << 7) ){ + if(call CC2420Config.isAddressRecognitionEnabled()){ + if(!(header.dest==call CC2420Config.getShortAddr() || header.dest==AM_BROADCAST_ADDR)){ + packetLength = header.length + 1; + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + } + if(SECURITYLOCK == 1){ + call SpiResource.release(); + post waitTask(); + return; + }else{ + //We are going to decrypt so lock the registers + atomic SECURITYLOCK = 1; + + if (secHdrPos + sizeof(security_header_t) > RXFIFO_SIZE){ + temp = RXFIFO_SIZE - secHdrPos; + call CSN.clr(); + atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, temp); + call CSN.set(); + call CSN.clr(); + atomic call RXFIFO_RAM.read(0,(uint8_t*)&secHdr+temp, sizeof(security_header_t) - temp); + call CSN.set(); + } else { + call CSN.clr(); + atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, sizeof(security_header_t)); + call CSN.set(); + } + + key = secHdr.keyID[0]; + + if (secHdr.secLevel == NO_SEC){ + mode = CC2420_NO_SEC; + micLength = 0; + }else if (secHdr.secLevel == CBC_MAC_4){ + mode = CC2420_CBC_MAC; + micLength = 4; + }else if (secHdr.secLevel == CBC_MAC_8){ + mode = CC2420_CBC_MAC; + micLength = 8; + }else if (secHdr.secLevel == CBC_MAC_16){ + mode = CC2420_CBC_MAC; + micLength = 16; + }else if (secHdr.secLevel == CTR){ + mode = CC2420_CTR; + micLength = 0; + }else if (secHdr.secLevel == CCM_4){ + mode = CC2420_CCM; + micLength = 4; + }else if (secHdr.secLevel == CCM_8){ + mode = CC2420_CCM; + micLength = 8; + }else if (secHdr.secLevel == CCM_16){ + mode = CC2420_CCM; + micLength = 16; + }else{ + atomic SECURITYLOCK = 0; + packetLength = header.length + 1; + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + + if(mode < 4 && mode > 0) { // if mode is valid - + securityOn = 1; + + memcpy(&nonceValue[3], &(secHdr.frameCounter), 4); + skip = secHdr.reserved; + + if(mode == CC2420_CBC_MAC || mode == CC2420_CCM){ + authentication = 1; + call CSN.clr(); + atomic call SECCTRL0.write((mode << CC2420_SECCTRL0_SEC_MODE) | + ((micLength-2)/2 << CC2420_SECCTRL0_SEC_M) | + (key << CC2420_SECCTRL0_SEC_RXKEYSEL) | + (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) | + (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ; + call CSN.set(); + }else{ + call CSN.clr(); + atomic call SECCTRL0.write((mode << CC2420_SECCTRL0_SEC_MODE) | + (1 << CC2420_SECCTRL0_SEC_M) | + (key << CC2420_SECCTRL0_SEC_RXKEYSEL) | + (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) | + (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ; + call CSN.set(); + } + + call CSN.clr(); +#ifndef TFRAMES_ENABLED + atomic call SECCTRL1.write(skip+11+sizeof(security_header_t)+((skip+11+sizeof(security_header_t))<<8)); +#else + atomic call SECCTRL1.write(skip+10+sizeof(security_header_t)+((skip+10+sizeof(security_header_t))<<8)); +#endif + call CSN.set(); + + call CSN.clr(); + atomic call RXNONCE.write(0, nonceValue, 16); + call CSN.set(); + + call CSN.clr(); + atomic call SRXDEC.strobe(); + call CSN.set(); + + atomic decLoopCount = 0; + post waitDecTask(); + return; + + }else{ + atomic SECURITYLOCK = 0; + packetLength = header.length + 1; + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + } + }else{ + packetLength = header.length + 1; + m_state = S_RX_LENGTH; + call SpiResource.release(); + beginReceive(); + return; + } + } +#endif /***************** SpiResource Events ****************/ event void SpiResource.granted() { +#ifdef CC2420_HW_SECURITY + if(m_state == S_RX_DEC){ + dec(); + }else{ + receive(); + } +#else receive(); +#endif } /***************** RXFIFO Events ****************/ @@ -191,15 +525,22 @@ implementation { async event void RXFIFO.readDone( uint8_t* rx_buf, uint8_t rx_len, error_t error ) { cc2420_header_t* header = call CC2420PacketBody.getHeader( m_p_rx_buf ); - cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf ); - uint8_t* buf = (uint8_t*) header; + uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2420_header_t)); + uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), header); rxFrameLength = buf[ 0 ]; switch( m_state ) { case S_RX_LENGTH: m_state = S_RX_FCF; - if ( rxFrameLength + 1 > m_bytes_left ) { +#ifdef CC2420_HW_SECURITY + packetLength = rxFrameLength+1; +#endif + if ( rxFrameLength + 1 > m_bytes_left +#ifdef CC2420_HW_SECURITY + || flush_flag == 1 +#endif + ) { // Length of this packet is bigger than the RXFIFO, flush it out. flush(); @@ -258,35 +599,43 @@ implementation { call SACK.strobe(); call CSN.set(); call CSN.clr(); - call RXFIFO.beginRead(buf + 1 + SACK_HEADER_LENGTH, - rxFrameLength - SACK_HEADER_LENGTH); + call RXFIFO.beginRead(buf + 1 + SACK_HEADER_LENGTH, + rxFrameLength - SACK_HEADER_LENGTH); return; } } - // Didn't flip CSn, we're ok to continue reading. call RXFIFO.continueRead(buf + 1 + SACK_HEADER_LENGTH, - rxFrameLength - SACK_HEADER_LENGTH); + rxFrameLength - SACK_HEADER_LENGTH); break; - + case S_RX_PAYLOAD: + call CSN.set(); - if(!m_missed_packets) { // Release the SPI only if there are no more frames to download call SpiResource.release(); } - if ( m_timestamp_size ) { - if ( rxFrameLength > 10 ) { - metadata->time = m_timestamp_queue[ m_timestamp_head ]; + //new packet is buffered up, or we don't have timestamp in fifo, or ack + if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() + || !m_timestamp_size + || rxFrameLength <= 10) { + call PacketTimeStamp.clear(m_p_rx_buf); + } + else { + if (m_timestamp_size==1) + call PacketTimeStamp.set(m_p_rx_buf, m_timestamp_queue[ m_timestamp_head ]); m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE; m_timestamp_size--; - } - } else { - metadata->time = 0xffff; + + if (m_timestamp_size>0) { + call PacketTimeStamp.clear(m_p_rx_buf); + m_timestamp_head = 0; + m_timestamp_size = 0; + } } - + // We may have received an ack that should be processed by Transmit // buf[rxFrameLength] >> 7 checks the CRC if ( ( buf[ rxFrameLength ] >> 7 ) && rx_buf ) { @@ -321,18 +670,36 @@ implementation { */ task void receiveDone_task() { cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf ); - uint8_t* buf = (uint8_t*) call CC2420PacketBody.getHeader( m_p_rx_buf );; - - metadata->crc = buf[ rxFrameLength ] >> 7; - metadata->lqi = buf[ rxFrameLength ] & 0x7f; - metadata->rssi = buf[ rxFrameLength - 1 ]; - m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data, - rxFrameLength ); + cc2420_header_t* header = call CC2420PacketBody.getHeader( m_p_rx_buf); + uint8_t length = header->length; + uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2420_header_t)); + uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), header); + metadata->crc = buf[ length ] >> 7; + metadata->lqi = buf[ length ] & 0x7f; + metadata->rssi = buf[ length - 1 ]; + + if (passesAddressCheck(m_p_rx_buf) && length >= CC2420_SIZE) { +#ifdef CC2420_HW_SECURITY + if(securityOn == 1){ + if(m_missed_packets > 0){ + m_missed_packets --; + } + if(authentication){ + length -= micLength; + } + } + micLength = 0; + securityOn = 0; + authentication = 0; +#endif + m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data, + length - CC2420_SIZE); + } atomic receivingPacket = FALSE; waitForNextPacket(); } - + /****************** CC2420Config Events ****************/ event void CC2420Config.syncDone( error_t error ) { } @@ -343,7 +710,6 @@ implementation { */ void beginReceive() { m_state = S_RX_LENGTH; - atomic receivingPacket = TRUE; if(call SpiResource.isOwner()) { receive(); @@ -360,7 +726,16 @@ implementation { * Flush out the Rx FIFO */ void flush() { +#ifdef CC2420_HW_SECURITY + flush_flag = 0; + pos =0; + packetLength =0; + micLength = 0; + securityOn = 0; + authentication = 0; +#endif reset_state(); + call CSN.set(); call CSN.clr(); call SFLUSHRX.strobe(); @@ -404,14 +779,20 @@ implementation { * If the line stays low without generating an interrupt, that means * there's still more data to be received. */ + if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() ) { // A new packet is buffered up and ready to go if ( m_missed_packets ) { m_missed_packets--; } - - beginReceive(); - +#ifdef CC2420_HW_SECURITY + call SpiResource.release(); + m_state = S_RX_DEC; + beginDec(); +#else + beginReceive(); +#endif + } else { // Wait for the next packet to arrive m_state = S_STARTED; @@ -432,4 +813,18 @@ implementation { m_missed_packets = 0; } + /** + * @return TRUE if the given message passes address recognition + */ + bool passesAddressCheck(message_t *msg) { + cc2420_header_t *header = call CC2420PacketBody.getHeader( msg ); + + if(!(call CC2420Config.isAddressRecognitionEnabled())) { + return TRUE; + } + + return (header->dest == call CC2420Config.getShortAddr() + || header->dest == AM_BROADCAST_ADDR); + } + }