Skip to content

Commit

Permalink
Reduce memory-allocations in PrfAesCmac.compute.
Browse files Browse the repository at this point in the history
The function now only allocates 4 objects with a combined size of 144 bytes.

Before this change, the function allocated 41104 bytes and 1284 object when the input data had size 10 kB.

This change also reduces the memory consumption of AES-SIV: for a 10 kB input, the  memory allocation for both encrypt and decrypt is reduced from about 62kB to about 21kB. And the runtime is also reduced by about 30%.

PiperOrigin-RevId: 646377300
Change-Id: I98fcada07d11553abcf596f9542d0102f66756af
  • Loading branch information
juergw authored and copybara-github committed Jun 25, 2024
1 parent 5383ad6 commit 862ecfc
Showing 1 changed file with 21 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/main/java/com/google/crypto/tink/subtle/PrfAesCmac.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ static int calcN(int dataLength) {
return (dataLength - 1) / AesUtil.BLOCK_SIZE + 1;
}

private static void xorBlock(final byte[] x, final byte[] y, int offsetY, byte[] output) {
for (int i = 0; i < AesUtil.BLOCK_SIZE; i++) {
output[i] = (byte) (x[i] ^ y[i + offsetY]);
}
}

// https://tools.ietf.org/html/rfc4493#section-2.4
@Override
public byte[] compute(final byte[] data, int outputLength) throws GeneralSecurityException {
Expand Down Expand Up @@ -120,15 +126,25 @@ public byte[] compute(final byte[] data, int outputLength) throws GeneralSecurit
byte[] x = new byte[AesUtil.BLOCK_SIZE];

// Step 6
byte[] y;
byte[] y = new byte[AesUtil.BLOCK_SIZE];
for (int i = 0; i < n - 1; i++) {
y = Bytes.xor(x, 0, data, i * AesUtil.BLOCK_SIZE, AesUtil.BLOCK_SIZE);
x = aes.doFinal(y);
xorBlock(x, data, i * AesUtil.BLOCK_SIZE, /* output= */ y);
int written = aes.doFinal(y, 0, AesUtil.BLOCK_SIZE, /* output= */ x);
if (written != AesUtil.BLOCK_SIZE) {
throw new IllegalStateException("Cipher didn't write full block");
}
}
y = Bytes.xor(mLast, x);
xorBlock(x, mLast, 0, /* output= */ y);

// Step 7
return Arrays.copyOf(aes.doFinal(y), outputLength);
int written = aes.doFinal(y, 0, AesUtil.BLOCK_SIZE, /* output= */ x);
if (written != AesUtil.BLOCK_SIZE) {
throw new IllegalStateException("Cipher didn't write full block");
}
if (x.length == outputLength) {
return x;
}
return Arrays.copyOf(x, outputLength);
}

// https://tools.ietf.org/html/rfc4493#section-2.3
Expand Down

0 comments on commit 862ecfc

Please sign in to comment.