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.
*
* 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.
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
private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
private int sizeOfAAD = 0;
@ -380,12 +383,10 @@ final class GaloisCounterMode extends FeedbackCipher {
// Utility to process the last block; used by encryptFinal and decryptFinal
void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs,
boolean isEncrypt) throws IllegalBlockSizeException {
// process data in 'in'
gctrPAndC.doFinal(in, inOfs, len, out, outOfs);
processed += len;
byte[] ct;
int ctOfs;
int ilen = len; // internal length
if (isEncrypt) {
ct = out;
ctOfs = outOfs;
@ -393,14 +394,38 @@ final class GaloisCounterMode extends FeedbackCipher {
ct = in;
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;
if (lastLen != 0) {
ghashAllToS.update(ct, ctOfs, len - lastLen);
byte[] padded =
expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen);
ghashAllToS.update(padded);
ghashAllToS.update(
expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen));
} else {
ghashAllToS.update(ct, ctOfs, len);
ghashAllToS.update(ct, ctOfs, ilen);
}
}
@ -562,6 +587,9 @@ final class GaloisCounterMode extends FeedbackCipher {
System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
len -= tagLenBytes;
// If decryption is in-place or there is buffered "ibuffer" data, copy
// the "in" byte array into the ibuffer before proceeding.
if (in == out || ibuffer.size() > 0) {
if (len > 0) {
ibuffer.write(in, inOfs, len);
}
@ -571,6 +599,7 @@ final class GaloisCounterMode extends FeedbackCipher {
inOfs = 0;
len = in.length;
ibuffer.reset();
}
if (len > 0) {
doLastBlock(in, inOfs, len, out, outOfs, false);