/*funzione di ricezione della frame inviata dal nodo di controllo * contenente il segreto cifrato */ void onJoinResponse(){ if(!memcmp(frame.sourceID,IDCONTROLLO,IDLEN) && *((uint32_t*)frame.timestamp)>timestamp){ uint32 cipherlen=SECRETLEN; //decifratura del msg e inserimento del segreto nella struttura SEC_HMAC_handle if(SEC_Decrypt(&sch,frame.msg,cipherlen,shh.secret,&(shh.secretlen)) != SEC_STATE_OK){ //LOG } if(SEC_HMAC_verify(&shh,&frame,HMAC_LENGTH,frame.digest)==SEC_STATE_HMAC_VERIFY_OK){ timestamp = *((uint32_t*)frame.timestamp); cleanVector(&frame,sizeof(frame)); //preparo la frame di ack frame.ID=SEC_JOIN_ACK; memcpy(frame.sourceID, STM32_UUID, IDLEN); // memcpy(frame.msg, STM32_UUID, IDLEN); SEC_HMAC(&shh,&frame,HMAC_LENGTH,frame.digest); // invio la frame di ack send_segment_best_effort((uint8*) &frame, sizeof(frame)); }else{ //hmac non verificato: rifiuta il segreto e ricomincio la procedura di join cleanVector(shh.secret,SECRETLEN); joinRequest(); } } //identita' non verificata, faccio qualcosa }
/************************************************* * Function: MSG_RecvDataFromCloud * Description: * Author: cxy * Returns: * Parameter: * History: *************************************************/ void ICACHE_FLASH_ATTR MSG_RecvDataFromCloud(u8 *pu8Data, u32 u32DataLen) { u32 u32RetVal; u16 u16PlainLen; u32RetVal = MSG_RecvData(&g_struRecvBuffer, pu8Data, u32DataLen); if (ZC_RET_OK == u32RetVal) { if (MSG_BUFFER_FULL == g_struRecvBuffer.u8Status) { u32RetVal = SEC_Decrypt((ZC_SecHead*)g_struRecvBuffer.u8MsgBuffer, g_struRecvBuffer.u8MsgBuffer + sizeof(ZC_SecHead), g_u8MsgBuildBuffer, &u16PlainLen); /*copy data*/ memcpy(g_struRecvBuffer.u8MsgBuffer, g_u8MsgBuildBuffer, u16PlainLen); g_struRecvBuffer.u32Len = u16PlainLen; if (ZC_RET_OK == u32RetVal) { u32RetVal = MSG_PushMsg(&g_struRecvQueue, (u8*)&g_struRecvBuffer); } } } return; }
void onJoinRequest() { /* all'atto di una richiesta: * - in base al mittente prelevo la chiave in tabella * - decifro il messaggio con la chiave prelevata * - costruisco il pacchetto di risposta col segreto cifrato * - invio il pacchetto cifrato e firmato */ if (!checkAckByID(&wl, frame.sourceID)) { sch.key = SearchKeyByID(&wl, frame.sourceID); sch.iv = sch.key; //il messaggio conterra' l'id che e' di 12 byte ma AES lavora con blocchi da 16 uint32 ciplen = 16; uint8 plain[16]; uint32 plainlen; SEC_StateTypeDef stato; stato = SEC_Decrypt(&sch, frame.msg, ciplen, plain, &plainlen); int result = memcmp(plain, frame.sourceID, IDLEN); if (result == 0) { //Costruisco il pacchetto di risposta della JOIN cleanVector((uint8*) &frame, sizeof(frame)); uint32 ciphertextLen; SEC_Encrypt(&sch, secret, SECRETLEN, frame.msg, &ciphertextLen); frame.ID = SEC_JOIN_RES; memcpy(frame.sourceID, STM32_UUID, IDLEN); memcpy(frame.timestamp, ×tamp,TIMESTAMPLEN); timestamp++; SEC_HMAC(&shh, (uint8*) &frame, HMAC_LENGTH, frame.digest); send((uint8*) &frame); } } else { /* utente gi������ presente in rete (gi������ ������ stato ricevuto l'ack) oppure non in whitelist. * invia un alert all'amministratore che deve controllare se il nodo ������ fidato e, quindi, * pu������ riattivarlo (mettendo il campo 'ack' a 0) oppure si tratta di un tentativo * malevolo di accedere alla rete */ } }
/*funzione di ricezione della frame inviata dal nodo di controllo * contenente l'ok per far partire di nuovo il Join Protocol */ void onSecretChangeOk(){ // Quando il nodo OPERATIVO riceve la frame di CHANGE OK(guarda l��� ID frame): // SE "ID Source==ID_CONTROLLO��� // Decifra il msg // Parsing del MSG che dovr�� avere un TIMESTAMP valido // se CheckTimestamp �� OK // CHIAMA La JOINREQUEST if(!memcmp(frame.sourceID,IDCONTROLLO,IDLEN) ){ uint32 cipherlen = TIMESTAMPLEN; uint32 plaintextlen; byte in[MAX_LENGTH]; memcpy(in,frame.msg,MAX_LENGTH); //conterr�� il messaggio in chiaro (mi aspetto un timestamp valido) uint32_t plaintext; //decifratura del msg if(SEC_Decrypt(&sch,in,cipherlen,(uint8_t*)(&plaintext),&plaintextlen) != SEC_STATE_OK){ //LOG } //se il timestamp �� valido if(plaintext>timestamp){ //lo salvo e inizio la join timestamp = plaintext; joinRequest(); } } else{ //identita' non verificata, faccio qualcosa } }