Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

The embedded device is a low-power 8-bit microcontroller (memory usage is constrained to about 10kb code, 1kb ram). As the device is battery-powered and manual service should be minimal, more powerful processors are not an option.

Throughput is very limited, so performance is not too much of an issue.

The system we came up with is AES-ctr mode encryption with hmac-sha authentication:

// encryption_key, mac_key, device_id are all independent, secure random,
// unique per device pre-programmed values

// aes-ctr encryption (pseudocode)
first_nonce = nonce = device_id || counter++
for block in plaintext
    ciphertext.append(aes_ctr_encrypt_block(encryption_key, block, nonce))
    nonce = device_id || counter++ // counter is saved in non-volatile storage (e.g. flash or eeprom) to avoid re-using after power down

// authenticate nonce + ciphertext (pseudocode)
data = first_nonce || ciphertext
mac_tag = hmac_sha2(data, mac_key)

// send or store mac_tag, nonce and ciphertext
send(mag_tag || data)

The receiving side should then use the deviceID to look up the mac_tag and verify it matches. By checking if the counter is larger than the one previously received we want to eliminate replay attacks.

If the validation checks out, the data is decrypted.

Is this a secure system? Also, what would be the effect of truncating the output of hmac_sha2 to 128 bits?

share|improve this question

1 Answer 1

I understand the system as follows:

  • data blocks are enciphered per AES-CTR, using key encryption_key, with an IV made by concatenating device_id and a counter held in Flash or EEPROM, incremented at each use;
  • that enciphered data is integrity-protected by a 256-bit mac_tag computed using HMAC-SHA256 and mac_key.

That's theoretically sound if

  1. device_id is unique.
  2. encryption_key and mac_key are maintained secret, and preferably device-unique (e.g. factory-diversified by some sound key derivation function from device_id and a master key that does not leak; of course that works only if communication is between devices and a master holding the master key; for device-to-device communication, we are back to global shared key, or public-key cryptography).
  3. counter does not overlap or otherwise return to an earlier state.

Truncating mac_tag to 128 bits is fine, except if a regulatory requirement prescribes otherwise.

Beware however that it is very hard to keep anything secret in an embedded system not designed from the grounds up for that goal; there's JTAG port, probing, buffer overflows, other side channels, induced faults..

And then there are implementation goofs, including but not limited to: deciphering something on the receiving side even though it did not pass the integrity check; failing to check on the receiving side that the counter increases; effectively incrementing counter on the transmitting side only after transmission has started (including because of some RAM cache); otherwise missing goal 3 above because power loss during Flash or EEPROM update is hard to deal with reliably, especially facing an adversary that cuts power at the worse moment (including old Murphy causing a reset because the Flash charge pump induces a power glitch), and an interrupted erase or program results in bits that do not read reliably at the same value, depending on power supply voltage, temperature, aging, or Schrödinger's cat health.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.