Search code examples
javaaesbouncycastlecmacsiv-authenticated-encryption

How to use Bouncycastle's CMac


I'm trying to use BouncyCastle's CMac implementation but apparently I'm doing it wrong. At least the following unit test (based on RFC 5297 test vectors) fails:

@Test
public void testCMacOfZeros() {
    byte[] key = {(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc, //
            (byte) 0xfb, (byte) 0xfa, (byte) 0xf9, (byte) 0xf8, //
            (byte) 0xf7, (byte) 0xf6, (byte) 0xf5, (byte) 0xf4, //
            (byte) 0xf3, (byte) 0xf2, (byte) 0xf1, (byte) 0xf0, //
            (byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, //
            (byte) 0xf4, (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, //
            (byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xfb, //
            (byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff};

    byte[] zeros = new byte[16];

    byte[] result = new byte[16];

    CipherParameters params = new KeyParameter(key);
    BlockCipher aes = new AESEngine();
    CMac mac = new CMac(aes);
    mac.init(params);
    mac.update(zeros, 0, 16);
    mac.doFinal(result, 0);

    byte[] expected = {(byte) 0x0e, (byte) 0x04, (byte) 0xdf, (byte) 0xaf, //
            (byte) 0xc1, (byte) 0xef, (byte) 0xbf, (byte) 0x04, //
            (byte) 0x01, (byte) 0x40, (byte) 0x58, (byte) 0x28, //
            (byte) 0x59, (byte) 0xbf, (byte) 0x07, (byte) 0x3a};

    Assert.assertArrayEquals(expected, result);
}

I assume, that the CMac implementation itself is well tested, so I must miss something.


Solution

  • I found my mistake:

    SIV-AES uses AES in CMAC mode (S2V) and in counter mode (CTR). SIV- AES takes either a 256-, 384-, or 512-bit key (which is broken up into two equal-sized keys, one for S2V and the other for CTR)

    I should have used only the first 16 bytes from the given key.

    As expected, BouncyCastle works just fine.