cmac
The cmac library provides a portable implementation of the
Cipher-based Message Authentication Code specified in NIST SP 800-38B:
https://doi.org/10.6028/NIST.SP.800-38B
The AES-CMAC specialization and test vectors are also described in RFC 4493:
https://datatracker.ietf.org/doc/html/rfc4493.html
The library exports a single object, cmac, implementing the
cmac_protocol protocol with the predicates:
digest/4hex_digest/4digest/5hex_digest/5
The first argument is a block cipher object implementing the
block_cipher_prepared_key_protocol protocol from the
block_ciphers library. CMAC supports the standard 8-byte and 16-byte
block sizes. The currently available cipher objects are aes128,
aes192, and aes256, all using 16-byte blocks.
The digest/5 and hex_digest/5 predicates return the requested
number of leftmost digest bytes. The length must be between one and the
cipher block size. The communicating parties must agree on a fixed tag
length before a key is used and must not change it during the lifetime
of that key.
API documentation
Open the ../../apis/library_index.html#cmac link in a web browser.
Loading
To load all entities in this library, load the loader.lgt file:
| ?- logtalk_load(cmac(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(cmac(tester)).
Security considerations
CMAC authenticates data and provides integrity protection but does not encrypt data. Use an authenticated-encryption construction when confidentiality is also required.
Keep keys secret and generate them using a cryptographically secure source. NIST SP 800-38B recommends tags of at least 8 bytes as protection against guessing attacks. Applications comparing received and computed tags should use an appropriate constant-time comparison operation.
The portable block cipher implementations used by this library are not guaranteed to execute in constant time and make no side-channel resistance claims.
Examples
Compute the RFC 4493 AES-CMAC digest for an empty message:
| ?- Key = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c],
cmac::hex_digest(aes128, Key, [], Digest).
Digest = 'bb1d6929e95937287fa37d129b756746'
yes
Compute an 8-byte truncated AES-CMAC digest:
| ?- Key = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c],
Message = [0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a],
cmac::hex_digest(aes128, Key, Message, 8, Digest).
Digest = '070a16b46b4d4144'
yes