8201633: Problems with AES-GCM native acceleration

Reviewed-by: valeriep
This commit is contained in:
Anthony Scarpino 2019-02-11 13:23:20 -08:00
parent 6d98f3c4d7
commit 9eb1223ac0

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -61,6 +61,9 @@ final class GaloisCounterMode extends FeedbackCipher {
// can only be returned by the doFinal(...) call. // can only be returned by the doFinal(...) call.
private static final int MAX_BUF_SIZE = Integer.MAX_VALUE; private static final int MAX_BUF_SIZE = Integer.MAX_VALUE;
// data size when buffer is divided up to aid in intrinsics
private static final int TRIGGERLEN = 65536; // 64k
// buffer for AAD data; if null, meaning update has been called // buffer for AAD data; if null, meaning update has been called
private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
private int sizeOfAAD = 0; private int sizeOfAAD = 0;
@ -380,12 +383,10 @@ final class GaloisCounterMode extends FeedbackCipher {
// Utility to process the last block; used by encryptFinal and decryptFinal // Utility to process the last block; used by encryptFinal and decryptFinal
void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs, void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs,
boolean isEncrypt) throws IllegalBlockSizeException { boolean isEncrypt) throws IllegalBlockSizeException {
// process data in 'in'
gctrPAndC.doFinal(in, inOfs, len, out, outOfs);
processed += len;
byte[] ct; byte[] ct;
int ctOfs; int ctOfs;
int ilen = len; // internal length
if (isEncrypt) { if (isEncrypt) {
ct = out; ct = out;
ctOfs = outOfs; ctOfs = outOfs;
@ -393,14 +394,38 @@ final class GaloisCounterMode extends FeedbackCipher {
ct = in; ct = in;
ctOfs = inOfs; ctOfs = inOfs;
} }
// Divide up larger data sizes to trigger CTR & GHASH intrinsic quicker
if (len > TRIGGERLEN) {
int i = 0;
int tlen; // incremental lengths
// 96bit CTR x86 intrinsic
final int plen = AES_BLOCK_SIZE * 6;
// arbitrary formula to aid intrinsic without reaching buffer end
final int count = len / 1024;
while (count > i) {
tlen = gctrPAndC.update(in, inOfs, plen, out, outOfs);
ghashAllToS.update(ct, ctOfs, tlen);
inOfs += tlen;
outOfs += tlen;
ctOfs += tlen;
i++;
}
ilen -= count * plen;
processed += count * plen;
}
gctrPAndC.doFinal(in, inOfs, ilen, out, outOfs);
processed += ilen;
int lastLen = len % AES_BLOCK_SIZE; int lastLen = len % AES_BLOCK_SIZE;
if (lastLen != 0) { if (lastLen != 0) {
ghashAllToS.update(ct, ctOfs, len - lastLen); ghashAllToS.update(ct, ctOfs, len - lastLen);
byte[] padded = ghashAllToS.update(
expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen); expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen));
ghashAllToS.update(padded);
} else { } else {
ghashAllToS.update(ct, ctOfs, len); ghashAllToS.update(ct, ctOfs, ilen);
} }
} }
@ -562,15 +587,19 @@ final class GaloisCounterMode extends FeedbackCipher {
System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes); System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
len -= tagLenBytes; len -= tagLenBytes;
if (len > 0) { // If decryption is in-place or there is buffered "ibuffer" data, copy
ibuffer.write(in, inOfs, len); // the "in" byte array into the ibuffer before proceeding.
} if (in == out || ibuffer.size() > 0) {
if (len > 0) {
ibuffer.write(in, inOfs, len);
}
// refresh 'in' to all buffered-up bytes // refresh 'in' to all buffered-up bytes
in = ibuffer.toByteArray(); in = ibuffer.toByteArray();
inOfs = 0; inOfs = 0;
len = in.length; len = in.length;
ibuffer.reset(); ibuffer.reset();
}
if (len > 0) { if (len > 0) {
doLastBlock(in, inOfs, len, out, outOfs, false); doLastBlock(in, inOfs, len, out, outOfs, false);