diff --git a/src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java b/src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java index 6a11d677..a2f40492 100644 --- a/src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java +++ b/src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java @@ -78,6 +78,14 @@ public static Prf create(AesCmacPrfKey key) throws GeneralSecurityException { return new PrfAesCmac(key.getKeyBytes().toByteArray(InsecureSecretKeyAccess.get())); } + // Only visible for testing. + static int calcN(int dataLength) { + if (dataLength == 0) { + return 1; + } + return (dataLength - 1) / AesUtil.BLOCK_SIZE + 1; + } + // https://tools.ietf.org/html/rfc4493#section-2.4 @Override public byte[] compute(final byte[] data, int outputLength) throws GeneralSecurityException { @@ -92,7 +100,7 @@ public byte[] compute(final byte[] data, int outputLength) throws GeneralSecurit // is divided. Empty data is divided into 1 empty block. // Step 2: n = ceil(length / blocksize) // TODO(b/68969256): Adding a test that computes a CMAC of length 2**31-1. - int n = Math.max(1, (int) Math.ceil((double) data.length / AesUtil.BLOCK_SIZE)); + int n = calcN(data.length); // Step 3 boolean flag = (n * AesUtil.BLOCK_SIZE == data.length); diff --git a/src/test/java/com/google/crypto/tink/subtle/PrfAesCmacTest.java b/src/test/java/com/google/crypto/tink/subtle/PrfAesCmacTest.java index 713f0aab..cd39b228 100644 --- a/src/test/java/com/google/crypto/tink/subtle/PrfAesCmacTest.java +++ b/src/test/java/com/google/crypto/tink/subtle/PrfAesCmacTest.java @@ -83,6 +83,22 @@ public void testFipsCompatibility() throws Exception { () -> new PrfMac(new PrfAesCmac(CMAC_TEST_VECTORS[0].key), 16)); } + @Test + public void calcN() throws Exception { + // AesUtil.BLOCK_SIZE == 16 + assertThat(PrfAesCmac.calcN(0)).isEqualTo(1); + assertThat(PrfAesCmac.calcN(1)).isEqualTo(1); + assertThat(PrfAesCmac.calcN(16)).isEqualTo(1); + assertThat(PrfAesCmac.calcN(17)).isEqualTo(2); + assertThat(PrfAesCmac.calcN(32)).isEqualTo(2); + assertThat(PrfAesCmac.calcN(33)).isEqualTo(3); + assertThat(PrfAesCmac.calcN(48)).isEqualTo(3); + assertThat(PrfAesCmac.calcN(49)).isEqualTo(4); + assertThat(PrfAesCmac.calcN(0x7FFFFFF0)).isEqualTo(0x07FFFFFF); + assertThat(PrfAesCmac.calcN(0x7FFFFFF1)).isEqualTo(0x08000000); + assertThat(PrfAesCmac.calcN(Integer.MAX_VALUE)).isEqualTo(0x08000000); + } + @Test public void testMacTestVectors() throws Exception { Assume.assumeFalse(TinkFips.useOnlyFips());