bool signerAtsha204SoftSignMsg(MyMessage &msg) {
	// If we cannot fit any signature in the message, refuse to sign it
	if (mGetLength(msg) > MAX_PAYLOAD-2) {
		DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
		return false; 
	}

	// Calculate signature of message
	mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
	signerCalculateSignature(msg);

	if (DO_WHITELIST(msg.destination)) {
		// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
		_signing_sha256.init();
		for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
		_signing_sha256.write(msg.sender);
		for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_node_serial_info[i]);
		memcpy(_signing_hmac, _signing_sha256.result(), 32);
		DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
		DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
	}

	// Overwrite the first byte in the signature with the signing identifier
	_signing_hmac[0] = SIGNING_IDENTIFIER;

	// Transfer as much signature data as the remaining space in the message permits
	memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
	DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));

	return true;
}
bool signerAtsha204SoftGetNonce(MyMessage &msg) {
	DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);

	// We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value
	// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
	_signing_sha256.init();
	for (int i = 0; i < 32; i++) {
		_signing_sha256.write(random(256));
	}
	memcpy(_signing_current_nonce, _signing_sha256.result(), MAX_PAYLOAD);
	DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_current_nonce, 32);

	// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
	memset(&_signing_current_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_current_nonce)-MAX_PAYLOAD);

	// Transfer the first part of the nonce to the message
	msg.set(_signing_current_nonce, MAX_PAYLOAD);
	_signing_verification_ongoing = true;
	_signing_timestamp = millis(); // Set timestamp to determine when to purge nonce
	// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
	// Note that if message is "too" quick, and arrives before turnover, it will be rejected
	// but this is consider such a rare case that it is accepted and rejects are 'safe'
	if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) _signing_timestamp = 0;
	return true;
}
bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
	if (!_signing_verification_ongoing) {
		DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
		return false; 
	} else {
		// Make sure we have not expired
		if (!signerCheckTimer()) {
			return false; 
		}

		_signing_verification_ongoing = false;

		if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
			DEBUG_SIGNING_PRINTBUF(F("Incorrect signing identifier"), NULL, 0);
			return false; 
		}

		// Get signature of message
		DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));
		signerCalculateSignature(msg);

#ifdef MY_SIGNING_NODE_WHITELISTING
		// Look up the senders nodeId in our whitelist and salt the signature with that data
		size_t j;
		for (j=0; j < NUM_OF(_signing_whitelist); j++) {
			if (_signing_whitelist[j].nodeId == msg.sender) {
				DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
				_signing_sha256.init();
				for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
				_signing_sha256.write(msg.sender);
				for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_whitelist[j].serial[i]);
				memcpy(_signing_hmac, _signing_sha256.result(), 32);
				DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
				break;
			}
		}
		if (j == NUM_OF(_signing_whitelist)) {
			DEBUG_SIGNING_PRINTBUF(F("Sender not found in whitelist, message rejected!"), NULL, 0);
			return false;
		}
#endif

		// Overwrite the first byte in the signature with the signing identifier
		_signing_hmac[0] = SIGNING_IDENTIFIER;

		// Compare the caluclated signature with the provided signature
		if (memcmp(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg))) {
			DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
#ifdef MY_SIGNING_NODE_WHITELISTING
			DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);
#endif
			return false; 
		} else {
			DEBUG_SIGNING_PRINTBUF(F("Signature OK"), NULL, 0);
			return true;
		}
	}
}
Esempio n. 4
0
void setup()
{
    printf("Test: FIPS 180-2 B.1\n");
    printf("Expect:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad\n");
    printf("Result:");
    Sha256Class sha;
    sha.init();
    uint32_t value = 0x1010101;
    sha.write('a');    
    sha.write('b');
    sha.write('c');
    uint8_t *ans = sha.result();
    printHash(ans);
    printf("\n");

}
Esempio n. 5
0
void igc_writeline(char * line, bool sign = true)
{
	uint8_t l = strlen(line);
	uint16_t wl;

//	DEBUG("IGC:%s\n", line);

	strcpy_P(line + l, PSTR("\r\n"));
	l += 2;

	assert(f_write(&log_file, line, l, &wl) == FR_OK);
	assert(wl == l);
	assert(f_sync(&log_file) == FR_OK);

#ifndef IGC_NO_PRIVATE_KEY
	if (sign)
		for (uint8_t i = 0; i < l; i++)
			sha256.write(line[i]);
#endif
}
Esempio n. 6
0
uint8_t igc_start(char * path)
{
	char filename[128];

	uint8_t sec;
	uint8_t min;
	uint8_t hour;
	uint8_t day;
	uint8_t wday;
	uint8_t month;
	uint16_t year;

	char line[79];
	char id[32];

	sha256.init();

	IGC_PRIVATE_KEY_ADD;

	datetime_from_epoch(time_get_utc(), &sec, &min, &hour, &day, &wday, &month, &year);

	//XXX
	#define device_uid "DRP"

	sprintf_P(filename, PSTR("%sIGC"), path);
	DEBUG("IGC filename %s\n", filename);

	uint8_t res = f_open(&log_file, filename, FA_WRITE | FA_CREATE_ALWAYS);
	assert(res == FR_OK);
	DEBUG("f_open res = %02X\n", res);

	//cannot create file
	if (res != FR_OK)
		return false;

	//A record
	GetID_str(id);
	sprintf_P(line, PSTR("A%S%s:%s"), LOG_MID_P, device_uid, id);
	igc_writeline(line);

	//H records
	//H F DTE
	sprintf_P(line, PSTR("HFDTE%02u%02u%02u"), day, month, year % 100);
	igc_writeline(line);
//	//H F DTE
//	sprintf_P(line, PSTR("HFDTEDATE:%02u%02u%02u,%02u"), day, month, year  % 100, logger_flight_number);
//	igc_writeline(line);
	//H F PLT PILOT IN CHARGE
	sprintf_P(line, PSTR("HFPLTPILOTINCHARGE:%s"), config.logger.pilot);
	igc_writeline(line);
	//H F CM2 CREW 2
	sprintf_P(line, PSTR("HFCM2CREW2:NIL"));
	igc_writeline(line);
	//H F GTY GLIDER TYPE
	sprintf_P(line, PSTR("HFGTYGLIDERTYPE:%s"), config.logger.glider_type);
	igc_writeline(line);
	//H F GID GLIDER ID
	sprintf_P(line, PSTR("HFGIDGLIDERID:%s"), config.logger.glider_id);
	igc_writeline(line);
	//H F DTM GPS DATUM
	sprintf_P(line, PSTR("HFDTMGPSDATUM:WGS84"));
	igc_writeline(line);
	//H F RFW FIRMWARE VERSION
	sprintf_P(line, PSTR("HFRFWFIRMWAREVERSION:build %d"), BUILD_NUMBER);
	igc_writeline(line);
	//H F RHW HARDWARE VERSION
	sprintf_P(line, PSTR("HFRHWHARDWAREVERSION:drop_%d"), (hw_revision == HW_REW_1504) ? 1504 : 1506);
	igc_writeline(line);
	//H F FTY FR TYPE
	sprintf_P(line, PSTR("HFFTYFRTYPE:SkyBean,SkyDrop"));
	igc_writeline(line);
	//H F GPS RECEIVER
	sprintf_P(line, PSTR("HFGPSRECEIVER:Quectel,L80,22cm,18000m"));
	igc_writeline(line);
	//H F PRS PRESS ALT SENSOR
	sprintf_P(line, PSTR("HFPRSPRESSALTSENSOR:Measurement specialties,MS5611,25907m"));
	igc_writeline(line);
	//H F ALG ALT GPS
	sprintf_P(line, PSTR("HFALGALTGPS:GEO"));
	igc_writeline(line);
	//H F ALP
	sprintf_P(line, PSTR("HFALPALTPRESSURE:ISA"));
	igc_writeline(line);
	//H F TZN
	sprintf_P(line, PSTR("HFTZNTIMEZONE:%+0.1f"), config.system.time_zone / 2.0);
	igc_writeline(line);

#ifdef IGC_NO_PRIVATE_KEY
	//Developer note: we can't publish the private key for signing the IGC file

	//H F FRS
	sprintf_P(line, PSTR("HFFRSSECSUSPECTUSEVALIPROG:This file is not valid. Private key not available!"));
	igc_writeline(line);
#endif

	//dump the cache
//	DEBUG("IGC dump len %d\n", igc_pre_start_len);
	for (uint8_t i = igc_pre_start_len; i > 0; i--)
	{
		int8_t index = igc_pre_start_index - i;
		if (index < 0)
			index += IGC_PRE_START_BUFFER;

//		DEBUG("IGC dump %d\n", index);

		igc_pre_fix * pfix = &igc_pre_start_cache[index];

		int16_t galt = pfix->galt;
		char c = 'A';

		if (galt == 0x7FFF)
		{
			galt = 0;
			c = 'V';
		}

		sprintf_P(line, PSTR("B%02d%02d%02d%s%s%c%05d%05d"), pfix->hour, pfix->min, pfix->sec, pfix->cache_igc_latitude, pfix->cache_igc_longtitude, c, pfix->balt, galt);
		igc_writeline(line);
	}
//	igc_comment("End of cache");
	igc_write_grecord();

	return (fc.gps_data.valid) ? LOGGER_ACTIVE : LOGGER_WAIT_FOR_GPS;
}
// Helper to calculate signature of msg (returned in hmac)
static void signerCalculateSignature(MyMessage &msg) {
	memset(_signing_temp_message, 0, 32);
	memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
	DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
	DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), _signing_current_nonce, 32);

	// ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data:
	// 32 bytes zeroes
	// 32 bytes digest,
	// 1 byte OPCODE (0x11)
	// 1 byte Mode (0x04)
	// 2 bytes SlotID (0x0000)
	// 11 bytes zeroes
	// SN[8] (0xEE)
	// 4 bytes zeroes
	// SN[0:1] (0x0123)
	// 2 bytes zeroes

	// The digest is calculated as a SHA256 digest of the following:
	// 32 bytes message
	// 1 byte OPCODE (0x15)
	// 1 byte param1 (0x02)
	// 2 bytes param2 (0x0800)
	// SN[8] (0xEE)
	// SN[0:1] (0x0123)
	// 25 bytes zeroes
	// 32 bytes nonce

	// Calculate message digest first
	_signing_sha256.init();
	for (int i=0; i<32; i++) _signing_sha256.write(_signing_temp_message[i]);
	_signing_sha256.write(0x15); // OPCODE
	_signing_sha256.write(0x02); // param1
	_signing_sha256.write(0x08); // param2(1)
	_signing_sha256.write(0x00); // param2(2)
	_signing_sha256.write(0xEE); // SN[8]
	_signing_sha256.write(0x01); // SN[0]
	_signing_sha256.write(0x23); // SN[1]
	for (int i=0; i<25; i++) _signing_sha256.write(0x00);
	for (int i=0; i<32; i++) _signing_sha256.write(_signing_current_nonce[i]);
	// Purge nonce when used
	memset(_signing_current_nonce, 0xAA, 32);
	memcpy(_signing_temp_message, _signing_sha256.result(), 32);

	// Feed "message" to HMAC calculator
	_signing_sha256.initHmac(_signing_hmac_key,32); // Set the key to use
	for (int i=0; i<32; i++) _signing_sha256.write(0x00); // 32 bytes zeroes
	for (int i=0; i<32; i++) _signing_sha256.write(_signing_temp_message[i]); // 32 bytes digest
	_signing_sha256.write(0x11); // OPCODE
	_signing_sha256.write(0x04); // Mode
	_signing_sha256.write(0x00); // SlotID(1)
	_signing_sha256.write(0x00); // SlotID(2)
	for (int i=0; i<11; i++) _signing_sha256.write(0x00); // 11 bytes zeroes
	_signing_sha256.write(0xEE); // SN[8]
	for (int i=0; i<4; i++) _signing_sha256.write(0x00); // 4 bytes zeroes
	_signing_sha256.write(0x01); // SN[0]
	_signing_sha256.write(0x23); // SN[1]
	for (int i=0; i<2; i++) _signing_sha256.write(0x00); // 2 bytes zeroes

	memcpy(_signing_hmac, _signing_sha256.resultHmac(), 32);

	DEBUG_SIGNING_PRINTBUF(F("HMAC: "), _signing_hmac, 32);
}