📄 tinysecm.nc
字号:
} else if(compute_mac_state == COMPUTE_MAC_INITIALIZED) { result_t result; compute_mac_state = COMPUTE_MAC_BUSY; interruptEnable(); result = call MAC.incrementalMAC( &macContext, ((uint8_t*) ciphertext_rec_ptr)+incr_mac_start,amount); interruptDisable(); compute_mac_state = COMPUTE_MAC_INITIALIZED; result = rcombine(result,checkQueuedCrypto()); return result; } else { return FAIL; } } result_t computeMACIncrementalFinish() { if(!initialized) return FAIL; if(compute_mac_state == COMPUTE_MAC_IDLE) { // this is an error. state should be unreachable return FAIL; } else if(compute_mac_state == COMPUTE_MAC_INITIALIZED) { result_t result; compute_mac_state = COMPUTE_MAC_BUSY; interruptEnable(); result = call MAC.getIncrementalMAC( &macContext, ciphertext_rec_ptr->calc_mac, TINYSEC_MAC_LENGTH+TINYSEC_ACK_LENGTH); interruptDisable(); ciphertext_rec_ptr->validMAC = TRUE; if(ciphertext_rec_ptr->receiveDone) { verifyMAC(); } compute_mac_state = COMPUTE_MAC_IDLE; result = rcombine(result,checkQueuedCrypto()); return result; } else { return FAIL; } } result_t verifyMAC() { int i; if(!initialized) return FAIL; // indicates incremental MAC computation has not completed if(!ciphertext_rec_ptr->validMAC) { return FAIL; } dbg(DBG_CRYPTO,"MAC computed: %hx %hx %hx %hx, " "MAC received: %hx %hx %hx %hx\n", (ciphertext_rec_ptr->calc_mac)[0], (ciphertext_rec_ptr->calc_mac)[1], (ciphertext_rec_ptr->calc_mac)[2], (ciphertext_rec_ptr->calc_mac)[3], (ciphertext_rec_ptr->mac)[0], (ciphertext_rec_ptr->mac)[1], (ciphertext_rec_ptr->mac)[2], (ciphertext_rec_ptr->mac)[3]); // verify calculated MAC with one received in packet for(i=0;i<TINYSEC_MAC_LENGTH;i++) { if((ciphertext_rec_ptr->calc_mac)[i] != (ciphertext_rec_ptr->mac)[i]) { dbg(DBG_CRYPTO,"Invalid MAC byte %d - calcmac:%hx ciphermac:%hx\n",i, (ciphertext_rec_ptr->calc_mac)[i], (ciphertext_rec_ptr->mac)[i]); ciphertext_rec_ptr->validMAC = FALSE; cleartext_rec_ptr->crc = 0; return SUCCESS; } } cleartext_rec_ptr->crc = 1; return SUCCESS; } /***************** Receive code *****************************/ async command result_t TinySec.receiveInit( TOS_Msg_TinySecCompat* cleartext_ptr) { ciphertext_rec_ptr = &tinysec_rec_buffer; cleartext_rec_ptr = cleartext_ptr; RxByteCnt = 0; rxlength = TINYSEC_MSG_DATA_SIZE-TINYSEC_MAC_LENGTH; rxdecrypt = FALSE; // initialize state variables in receive buffer ciphertext_rec_ptr->cryptoDone = FALSE; ciphertext_rec_ptr->receiveDone = FALSE; ciphertext_rec_ptr->validMAC = FALSE; // reset crypto buffer variables computeMACBuffer.computeMACWaiting = FALSE; computeMACBuffer.computeMACInitWaiting = FALSE; decryptBuffer.decryptWaiting = FALSE; decryptBuffer.decryptInitWaiting = FALSE; computeMACBuffer.finishMACWaiting = FALSE; // flush crc cleartext_rec_ptr->crc = 0; return SUCCESS; } async event result_t TinySecRadio.byteReceived(uint8_t byte) { int8_t macRecCount=-1, decryptRecCount=-1; if(RxByteCnt < rxlength) { // this branch statement is a hack for when we skip // over the IV for non-encrypted packets. we add the TINYSEC_IV_SIZE if(!rxdecrypt && RxByteCnt == offsetof(struct TinySec_Msg,iv)) { RxByteCnt += TINYSEC_IV_LENGTH; ((uint8_t *) ciphertext_rec_ptr)[(int)RxByteCnt] = byte; RxByteCnt++; macRecCount = ((RxByteCnt - TINYSEC_IV_LENGTH) & (blockSize-1)) + TINYSEC_IV_LENGTH; decryptRecCount = RxByteCnt - offsetof(struct TinySec_Msg,enc); } else { ((uint8_t *) ciphertext_rec_ptr)[(int)RxByteCnt] = byte; RxByteCnt++; macRecCount = RxByteCnt & (blockSize-1); decryptRecCount = RxByteCnt - offsetof(struct TinySec_Msg,enc); } } else if(RxByteCnt < rxlength + TINYSEC_IV_LENGTH) { ciphertext_rec_ptr->mac[RxByteCnt-rxlength] = byte; RxByteCnt++; } dbg(DBG_CRYPTO,"TINYSEC: byteReceived() RxByteCnt=%d data=%hx " "recDataLength=%d macRecCount=%d decryptRecCount=%d.\n", RxByteCnt,byte,recDataLength,macRecCount,decryptRecCount); if(RxByteCnt < rxlength) { if(RxByteCnt == (offsetof(struct TinySec_Msg,length) + sizeof(((struct TinySec_Msg *)0)->length))) { // get real length recDataLength = ciphertext_rec_ptr->length & (TINYSEC_ENCRYPT_ENABLED_BIT-1); if(recDataLength > DATA_LENGTH) signal TinySec.receiveInitDone(FAIL,0,FALSE); if(ciphertext_rec_ptr->length & TINYSEC_ENABLED_BIT) { dbg(DBG_CRYPTO,"Detected TinySec bit.\n"); if(ciphertext_rec_ptr->length & TINYSEC_ENCRYPT_ENABLED_BIT) { dbg(DBG_CRYPTO,"Encryption enabled.\n"); rxdecrypt = TRUE; } else { dbg(DBG_CRYPTO,"Encryption disabled.\n"); rxdecrypt = FALSE; } rxlength = offsetof(struct TinySec_Msg,enc); if(recDataLength < blockSize && rxdecrypt) rxlength += blockSize; else rxlength += recDataLength; if(rxdecrypt) { signal TinySec.receiveInitDone(SUCCESS,rxlength,TRUE); } else { // zero out iv if encryption is not enabled memset(ciphertext_rec_ptr->iv,0,TINYSEC_IV_LENGTH); signal TinySec.receiveInitDone(SUCCESS, rxlength-TINYSEC_IV_LENGTH,TRUE); } postIncrementalMACInit(); } else { // TinySec not enabled rxlength = recDataLength + offsetof(struct TOS_Msg_TinySecCompat, data); signal TinySec.receiveInitDone(SUCCESS,rxlength,FALSE); } } else { // not length byte. // bytes before length byte will fail following checks. // this weird check is needed because of when we // skip RxByteCnt over the IV when encryption in not enabled. if(macRecCount == 0) macRecCount = blockSize; if(macRecCount >= blockSize) { // post MAC operation postIncrementalMAC(RxByteCnt-macRecCount,blockSize); } if(rxdecrypt) { if(decryptRecCount == 0) { postIncrementalDecryptInit(); } else if((decryptRecCount & (blockSize-1)) == 0) { postIncrementalDecrypt(decryptRecCount-blockSize,blockSize); } } } checkQueuedCrypto(); } else if(RxByteCnt == rxlength) { if(macRecCount == 0) macRecCount = blockSize; postIncrementalMAC(RxByteCnt-macRecCount,macRecCount); postIncrementalMACFinish(); if(rxdecrypt) { if((decryptRecCount & (blockSize-1)) == 0) { postIncrementalDecrypt(decryptRecCount-blockSize,blockSize); } else { postIncrementalDecrypt( decryptRecCount-(decryptRecCount & (blockSize-1)), decryptRecCount & (blockSize-1)); } } else { memcpy(cleartext_rec_ptr->data,ciphertext_rec_ptr->enc,recDataLength); } checkQueuedCrypto(); ciphertext_rec_ptr->cryptoDone = TRUE; cleartext_rec_ptr->group = TOS_AM_GROUP; if(ciphertext_rec_ptr->receiveDone) { signal TinySec.receiveDone(SUCCESS); } } else if(RxByteCnt == rxlength + TINYSEC_IV_LENGTH) { ciphertext_rec_ptr->receiveDone = TRUE; if(ciphertext_rec_ptr->validMAC) verifyMAC(); if(ciphertext_rec_ptr->cryptoDone) { signal TinySec.receiveDone(SUCCESS); } } else { // we have an error return FAIL; } return SUCCESS; } /****************** Send code ****************************/ async command uint16_t TinySec.sendInit(TOS_Msg_TinySecCompat* cleartext_ptr) { cleartext_send_ptr = cleartext_ptr; ciphertext_send_ptr = &tinysec_send_buffer; ciphertext_send_ptr->addr = cleartext_send_ptr->addr; ciphertext_send_ptr->length = cleartext_send_ptr->length; ciphertext_send_ptr->type = cleartext_send_ptr->type; sendDataLength = cleartext_send_ptr->length & (TINYSEC_ENCRYPT_ENABLED_BIT-1); dbg(DBG_CRYPTO,"TINYSEC: sendInit() Sending length = %d\n",sendDataLength); dbg(DBG_CRYPTO,"TINYSEC: sendInit() Length field = %d\n", ciphertext_send_ptr->length); // fix length fields that are too long if(sendDataLength > DATA_LENGTH) { sendDataLength = DATA_LENGTH; ciphertext_send_ptr->length = DATA_LENGTH | TINYSEC_ENABLED_BIT | (cleartext_send_ptr->length & TINYSEC_ENCRYPT_ENABLED_BIT); } if(cleartext_send_ptr->length & TINYSEC_ENCRYPT_ENABLED_BIT) txencrypt = TRUE; else txencrypt = FALSE; if(sendDataLength < blockSize && txencrypt) { txlength = blockSize + TINYSEC_MSG_DATA_SIZE - DATA_LENGTH - TINYSEC_MAC_LENGTH; } else { txlength = sendDataLength + TINYSEC_MSG_DATA_SIZE - DATA_LENGTH - TINYSEC_MAC_LENGTH; } TxByteCnt = -1; return txlength; } result_t computeMAC() { result_t result = call MAC.MAC(&macContext, (uint8_t*) &(ciphertext_send_ptr->addr), txlength, ciphertext_send_ptr->calc_mac, TINYSEC_MAC_LENGTH+TINYSEC_ACK_LENGTH); // copy calculated mac to mac field. reason is because extra byte // was calculated and stored in ack_byte. ack_byte is // currently not used. memcpy(ciphertext_send_ptr->mac,ciphertext_send_ptr->calc_mac, TINYSEC_MAC_LENGTH); dbg(DBG_CRYPTO,"MAC: computed: %hx %hx %hx %hx\n", (ciphertext_send_ptr->mac)[0], (ciphertext_send_ptr->mac)[1], (ciphertext_send_ptr->mac)[2], (ciphertext_send_ptr->mac)[3]); return result; } // for padding out input less than a block size result_t addPadding(TOS_Msg_TinySecCompat* bufptr, uint16_t dataLength) { uint16_t r = call Random.rand(); uint8_t i = 0; for(i=dataLength;i<blockSize-1;i=i+2) { memcpy((bufptr->data)+i,&r,2); r = call Random.rand(); } if(i == (blockSize-1)) { memcpy((bufptr->data)+i,&r,1); } return SUCCESS; } result_t encrypt() { // number of header bytes we use for implicit IV uint16_t ivLengthRemaining = sizeof(ciphertext_send_ptr->addr) + sizeof(ciphertext_send_ptr->type) + sizeof(ciphertext_send_ptr->length); result_t result; uint8_t i; if(ivLengthRemaining > (blockSize - TINYSEC_IV_LENGTH)) ivLengthRemaining = blockSize - TINYSEC_IV_LENGTH; // copy current iv into cipher buffer iv field memcpy(&(ciphertext_send_ptr->iv),iv,TINYSEC_IV_LENGTH); // fill in remaining space with addr, AM type, and length memcpy(iv+TINYSEC_IV_LENGTH,&(ciphertext_send_ptr->addr),ivLengthRemaining); // zero out the rest of the iv for(i=ivLengthRemaining+TINYSEC_IV_LENGTH;i<blockSize;i++) { iv[i] = 0; } if(sendDataLength < blockSize) { // pad if data length less than blockSize addPadding(cleartext_send_ptr,sendDataLength); result = call BlockCipherMode.encrypt(&cipherModeContext, cleartext_send_ptr->data, ciphertext_send_ptr->enc, blockSize,iv); } else { result = call BlockCipherMode.encrypt(&cipherModeContext, cleartext_send_ptr->data, ciphertext_send_ptr->enc, sendDataLength,iv); } i=0; // update IV by one // last two bytes of explicit IV is TOS_LOCAL_ADDRESS while(i<TINYSEC_IV_LENGTH-TINYSEC_NODE_ID_SIZE) { if(iv[i] == 0xff) { iv[i] = 0; } else { iv[i] = iv[i] + 1; break; } i++; } return result; } result_t noEncrypt() { // zero out IV if no encryption memset(ciphertext_send_ptr->iv,0,TINYSEC_IV_LENGTH); memcpy(ciphertext_send_ptr->enc,cleartext_send_ptr->data,sendDataLength); return SUCCESS; } async command result_t TinySec.send() { result_t r1,r2; interruptEnable(); if(txencrypt) r1 = encrypt(); else r1 = noEncrypt(); r2 = computeMAC(); interruptDisable(); return rcombine(r1,r2); } async event uint8_t TinySecRadio.getTransmitByte() { uint8_t NextTxByte=0; TxByteCnt++; if (TxByteCnt < txlength) { // skip iv if encryption not enabled if(TxByteCnt == offsetof(struct TinySec_Msg, iv) && !txencrypt) TxByteCnt += TINYSEC_IV_LENGTH; NextTxByte = ((uint8_t *)&tinysec_send_buffer)[(TxByteCnt)]; dbg(DBG_CRYPTO,"TINYSEC: getTransmitByte() byte=%d data=%hx\n", TxByteCnt+1,NextTxByte); } else if(TxByteCnt < txlength + TINYSEC_MAC_LENGTH) { NextTxByte = tinysec_send_buffer.mac[TxByteCnt-txlength]; dbg(DBG_CRYPTO,"TINYSEC: getTransmitByte() byte=%d data=%hx\n", TxByteCnt+1,NextTxByte); if(TxByteCnt == txlength + TINYSEC_MAC_LENGTH - 1) { signal TinySec.sendDone(SUCCESS); dbg(DBG_CRYPTO,"TINYSEC: getTransmitByte() signaling send done\n"); } } else { // this is an error state dbg(DBG_CRYPTO,"TINYSEC: getTransmitByte() signaling send done (FAIL)\n"); signal TinySec.sendDone(FAIL); } return NextTxByte; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -