uint16_t crc16_calculate(const uint8_t *buf, size_t len) { uint16_t crc; crc16_init(&crc); crc16_update(&crc, buf, len); return crc; }
//! @brief Calculate crc over framing data packet. static uint16_t calculate_framing_crc16(framing_data_packet_t * packet, const uint8_t * data) { uint16_t crc16; // Initialize the CRC16 information crc16_data_t crcInfo; crc16_init(&crcInfo); // Run CRC on all header bytes besides the CRC field crc16_update(&crcInfo, (uint8_t *)&packet->header.startByte, sizeof(framing_data_packet_t) - sizeof(uint16_t)); // Continue running CRC on any payload bytes crc16_update(&crcInfo, data, packet->length); // Finalize the CRC calculations crc16_finalize(&crcInfo, &crc16); return crc16; }
uint8_t reprog_restart(void) { uint16_t address, length, crc; /* Read code length and crc */ eeprom_mcu_read((uint8_t*)&length, 3, 4); eeprom_mcu_read((uint8_t*)&crc, 5, 6); /* Calculate CRC and compare to stored value */ crc16_init(); for (uint16_t i = CODE_HEADER_SIZE; i < length + CODE_HEADER_SIZE; i++) { eeprom_mcu_read(buffer, address, address); crc16_update(buffer[0]); } /* Only restart if CRC matches */ if (crc != crc16_read()) { return false; } /* Copy from upper half of memory to lower half */ for (uint8_t j = 0; j < (MEM_SIZE / BUFFER_SIZE); j++) { address = j * BUFFER_SIZE; eeprom_mcu_read(buffer, address, address + (BUFFER_SIZE - 1)); mem_eeprom_CodeSection(true); eeprom_mcu_write(buffer, address, address + (BUFFER_SIZE - 1)); mem_eeprom_CodeSection(false); } /* Reset address = 0x8000 (bootloader) */ RSTREAS |= BIT(RFLR1); /* Start watchdog timer */ regx_write(WD, 1); /* Wait for WDT to timeout */ for(;;) { ; } }
/* mode = 0/1/2 0=init, 1=update, 2=finalize */ uint32_t update_crc_ne(uint32_t old_crc, int crclen, void *data, int datasiz, int datalen, int mode) { uint32_t seed=old_crc; uint32_t new_crc; crc16_t crc16; crc24_t crc24; crc32_t crc32; unsigned int mask=0 ; int data_len=datasiz*datalen ; new_crc = seed ; if( (*little_endian) & (datasiz>1)){ /* multibyte tokens on little endian machine */ mask = datasiz-1 ; /* 0/1/3/7 magic mask to get stitching order count on little endian machines */ } if (crclen==16) { crc16 = seed & 0xFFFF ; if(mode==0) crc16 = crc16_init() ; crc16 = crc16_update_le(crc16, (const unsigned char *) data, data_len, mask) ; if(mode==2) crc16 = crc16_finalize(crc16) ; new_crc = crc16 ; } else if (crclen==24) { crc24 = seed & 0xFFFFFF ; if(mode==0) crc24 = crc24_init() ; crc24 = crc24_update_le(crc24, (const unsigned char *) data, data_len, mask) ; if(mode==2) crc24 = crc24_finalize(crc24) ; new_crc = crc24 ; } else if (crclen==32) { crc32 = seed & 0xFFFFFFFF ; if(mode==0) crc32 = crc32_init() ; crc32 = crc32_update_le(crc32, (const unsigned char *) data, data_len, mask) ; if(mode==2) crc32 = crc32_finalize(crc32) ; new_crc = crc32 ; } else { new_crc = seed ; } return new_crc; }
int CHashManager::HashFile(char *pszFile) { FILE *fp = NULL; unsigned char pBuf[SIZE_HASH_BUFFER]; unsigned long uRead = 0; unsigned char pTemp[256]; char szTemp[RH_MAX_BUFFER]; int i = 0; printf("File: <"); printf(pszFile); printf(">"); printf(CPS_NEWLINE); fp = fopen(pszFile, "rb"); if(fp == NULL) return RH_CANNOT_OPEN_FILE; if(m_bAlgorithm[HASHID_CRC16]) crc16_init(&m_crc16); if(m_bAlgorithm[HASHID_CRC16CCITT]) crc16ccitt_init(&m_crc16ccitt); if(m_bAlgorithm[HASHID_CRC32]) crc32Init(&m_crc32); if(m_bAlgorithm[HASHID_FCS_16]) fcs16_init(&m_fcs16); if(m_bAlgorithm[HASHID_FCS_32]) fcs32_init(&m_fcs32); if(m_bAlgorithm[HASHID_GHASH_32_3] || m_bAlgorithm[HASHID_GHASH_32_5]) m_ghash.Init(); if(m_bAlgorithm[HASHID_GOST]) gosthash_reset(&m_gost); if(m_bAlgorithm[HASHID_HAVAL]) haval_start(&m_haval); if(m_bAlgorithm[HASHID_MD2]) m_md2.Init(); if(m_bAlgorithm[HASHID_MD4]) MD4Init(&m_md4); if(m_bAlgorithm[HASHID_MD5]) MD5Init(&m_md5, 0); if(m_bAlgorithm[HASHID_SHA1]) sha1_begin(&m_sha1); if(m_bAlgorithm[HASHID_SHA2_256]) sha256_begin(&m_sha256); if(m_bAlgorithm[HASHID_SHA2_384]) sha384_begin(&m_sha384); if(m_bAlgorithm[HASHID_SHA2_512]) sha512_begin(&m_sha512); if(m_bAlgorithm[HASHID_SIZE_32]) sizehash32_begin(&m_uSizeHash32); if(m_bAlgorithm[HASHID_TIGER]) tiger_init(&m_tiger); while(1) { uRead = fread(pBuf, 1, SIZE_HASH_BUFFER, fp); if(uRead != 0) { if(m_bAlgorithm[HASHID_CRC16]) crc16_update(&m_crc16, pBuf, uRead); if(m_bAlgorithm[HASHID_CRC16CCITT]) crc16ccitt_update(&m_crc16ccitt, pBuf, uRead); if(m_bAlgorithm[HASHID_CRC32]) crc32Update(&m_crc32, pBuf, uRead); if(m_bAlgorithm[HASHID_FCS_16]) fcs16_update(&m_fcs16, pBuf, uRead); if(m_bAlgorithm[HASHID_FCS_32]) fcs32_update(&m_fcs32, pBuf, uRead); if(m_bAlgorithm[HASHID_GHASH_32_3] || m_bAlgorithm[HASHID_GHASH_32_5]) m_ghash.Update(pBuf, uRead); if(m_bAlgorithm[HASHID_GOST]) gosthash_update(&m_gost, pBuf, uRead); if(m_bAlgorithm[HASHID_HAVAL]) haval_hash(&m_haval, pBuf, uRead); if(m_bAlgorithm[HASHID_MD2]) m_md2.Update(pBuf, uRead); if(m_bAlgorithm[HASHID_MD4]) MD4Update(&m_md4, pBuf, uRead); if(m_bAlgorithm[HASHID_MD5]) MD5Update(&m_md5, pBuf, uRead); if(m_bAlgorithm[HASHID_SHA1]) sha1_hash(pBuf, uRead, &m_sha1); if(m_bAlgorithm[HASHID_SHA2_256]) sha256_hash(pBuf, uRead, &m_sha256); if(m_bAlgorithm[HASHID_SHA2_384]) sha384_hash(pBuf, uRead, &m_sha384); if(m_bAlgorithm[HASHID_SHA2_512]) sha512_hash(pBuf, uRead, &m_sha512); if(m_bAlgorithm[HASHID_SIZE_32]) sizehash32_hash(&m_uSizeHash32, uRead); if(m_bAlgorithm[HASHID_TIGER]) tiger_process(&m_tiger, pBuf, uRead); } if(uRead != SIZE_HASH_BUFFER) break; } fclose(fp); fp = NULL; // SizeHash-32 is the first hash, because it's the simplest one, // the fastest, and most widely used one. ;-) if(m_bAlgorithm[HASHID_SIZE_32]) { sizehash32_end(&m_uSizeHash32); printf(SZ_SIZEHASH_32); printf(SZ_HASHPRE); printf("%08X", m_uSizeHash32); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_CRC16]) { crc16_final(&m_crc16); printf(SZ_CRC16); printf(SZ_HASHPRE); printf("%04X", m_crc16); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_CRC16CCITT]) { crc16ccitt_final(&m_crc16ccitt); printf(SZ_CRC16CCITT); printf(SZ_HASHPRE); printf("%04X", m_crc16ccitt); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_CRC32]) { crc32Finish(&m_crc32); printf(SZ_CRC32); printf(SZ_HASHPRE); printf("%08X", m_crc32); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_FCS_16]) { fcs16_final(&m_fcs16); printf(SZ_FCS_16); printf(SZ_HASHPRE); printf("%04X", m_fcs16); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_FCS_32]) { fcs32_final(&m_fcs32); printf(SZ_FCS_32); printf(SZ_HASHPRE); printf("%08X", m_fcs32); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_GHASH_32_3]) { m_ghash.FinalToStr(szTemp, 3); printf(SZ_GHASH_32_3); printf(SZ_HASHPRE); printf(szTemp); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_GHASH_32_5]) { m_ghash.FinalToStr(szTemp, 5); printf(SZ_GHASH_32_5); printf(SZ_HASHPRE); printf(szTemp); printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_GOST]) { gosthash_final(&m_gost, pTemp); printf(SZ_GOST); printf(SZ_HASHPRE); for(i = 0; i < 32; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_HAVAL]) { haval_end(&m_haval, pTemp); printf(SZ_HAVAL); printf(SZ_HASHPRE); for(i = 0; i < 32; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_MD2]) { m_md2.TruncatedFinal(pTemp, 16); printf(SZ_MD2); printf(SZ_HASHPRE); for(i = 0; i < 16; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_MD4]) { MD4Final(pTemp, &m_md4); printf(SZ_MD4); printf(SZ_HASHPRE); for(i = 0; i < 16; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_MD5]) { MD5Final(&m_md5); printf(SZ_MD5); printf(SZ_HASHPRE); for(i = 0; i < 16; i++) { fmtFixHashOutput(i); printf("%02X", m_md5.digest[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_SHA1]) { sha1_end(pTemp, &m_sha1); printf(SZ_SHA1); printf(SZ_HASHPRE); for(i = 0; i < 20; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_SHA2_256]) { sha256_end(pTemp, &m_sha256); printf(SZ_SHA2_256); printf(SZ_HASHPRE); for(i = 0; i < 32; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_SHA2_384]) { sha384_end(pTemp, &m_sha384); printf(SZ_SHA2_384); printf(SZ_HASHPRE); for(i = 0; i < 48; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_SHA2_512]) { sha512_end(pTemp, &m_sha512); printf(SZ_SHA2_512); printf(SZ_HASHPRE); for(i = 0; i < 64; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[i]); } printf(CPS_NEWLINE); } if(m_bAlgorithm[HASHID_TIGER]) { tiger_done(&m_tiger, pTemp); printf(SZ_TIGER); printf(SZ_HASHPRE); for(i = 0; i < 8; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[7-i]); } for(i = 8; i < 16; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[23-i]); } for(i = 16; i < 24; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[39-i]); } printf(CPS_NEWLINE); } return RH_SUCCESS; }
/* Returns the length of the file received, or 0 on error: */ int ymodem_receive(char *buf, unsigned int length) { unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; int packet_length, i, file_done, session_done, crc_tries, crc_nak, use_crc; unsigned int packets_received, errors, timeout, first_try = 1; char file_name[FILE_NAME_LENGTH], file_size[FILE_SIZE_LENGTH], *file_ptr; char *buf_ptr; unsigned long size = 0; #ifdef CONFIG_MD5 unsigned int sum[MD5_SUM_WORDS]; #endif if(crc16_init() < 0){ putstr("Unable to generate CRC16 lookup table\r\n"); return 0; } putstr("ready for YMODEM transfer...\r\n"); /* Give the user time to frantically type in the file name: */ timeout = INITIAL_TIMEOUT; for(session_done = 0, errors = 0; ; ){ crc_tries = crc_nak = use_crc = 1; if(!first_try) putc(CRC); first_try = 0; for(packets_received = 0, file_done = 0, buf_ptr = buf; ; ){ switch(receive_packet(packet_data, &packet_length, use_crc, timeout)){ case 0: errors = 0; switch(packet_length){ case -1: /* abort */ putc(ACK); return 0; case 0: /* end of transmission */ putc(ACK); /* Should add some sort of sanity check on the number of * packets received and the advertised file length. */ file_done = 1; break; default: /* normal packet */ if((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)){ putc(NAK); } else { if(packets_received == 0){ /* The spec suggests that the whole data section should * be zeroed, but I don't think all senders do this. If * we have a NULL filename and the first few digits of * the file length are zero, we'll call it empty. */ for(i = PACKET_HEADER; i < PACKET_HEADER + 4; ++i) if(packet_data[i] != 0) break; if(i < PACKET_HEADER + 4){ /* filename packet has data */ for(file_ptr = packet_data + PACKET_HEADER, i = 0; *file_ptr && i < FILE_NAME_LENGTH;) file_name[i++] = *file_ptr++; file_name[i++] = '\0'; for(++file_ptr, i = 0; *file_ptr != ' ' && i < FILE_SIZE_LENGTH;) file_size[i++] = *file_ptr++; file_size[i++] = '\0'; size = strtoul(file_size, NULL, 0); if(size > length){ putc(CAN); putc(CAN); delay_seconds(3); putstr("Receive buffer too small ("); putHexInt32(length); putLabeledWord(") to accept file size ", size); return 0; } putc(ACK); putc(crc_nak ? CRC : NAK); crc_nak = 0; } else { /* filename packet is empty; end session */ putc(ACK); file_done = 1; session_done = 1; break; } } else { /* This shouldn't happen, but we check anyway in case the * sender lied in its filename packet: */ if((buf_ptr + packet_length) - buf > length){ putc(CAN); putc(CAN); delay_seconds(3); putLabeledWord("Sender exceeded size of receive buffer: ", length); return 0; } memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length); buf_ptr += packet_length; putc(ACK); } ++packets_received; } /* sequence number ok */ } break; default: if(++errors >= ((packets_received == 0 ? MAX_CRC_TRIES : 0) + MAX_ERRORS)){ putc(CAN); putc(CAN); delay_seconds(1); putstr("Too many errors during receive; giving up.\r\n"); return 0; } if(packets_received == 0){ if(crc_tries < MAX_CRC_TRIES) { ++crc_tries; timeout = CRC_TIMEOUT; } else { crc_nak = use_crc = 0; timeout = NAK_TIMEOUT; } } putc(crc_nak ? CRC : NAK); } if(file_done) break; } /* receive packets */ if(session_done) break; } /* receive files */ #ifdef CONFIG_MD5 /* Give sender time to exit so that the subsequent MD5 display will be * visible on the user's terminal: */ delay_seconds(1); md5_sum(buf, size, sum); md5_display(sum); putstr(" "); putstr(file_name); putstr("\r\n"); #endif return size; }